home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / dev / misc / FD2Pragma.lha / Source / FD2Pragma.c next >
Encoding:
C/C++ Source or Header  |  1999-07-29  |  128.9 KB  |  5,054 lines

  1. #define NAME     "FD2Pragma"
  2. #define VERSION  "2"
  3. #define REVISION "89"
  4. //#define DEBUG
  5. //#define DEBUG_OLD
  6.  
  7. /* Programmheader
  8.  
  9.     Name:        FD2Pragma
  10.     Author:     SDI
  11.     Distribution:    PD
  12.     Description:    creates pragmas files, lvo files and stub functions
  13.     Compileropts:    -
  14.     Linkeropts:    -gd -l amiga
  15.  
  16.  1.2    : added pragmas for the Dice compiler. Available via switch "Dice".
  17.     added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  18.     turn on the default (except that Maxon expects pragma files to be
  19.     called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  20.     Dice, except that SAS supports the pragma tagcall.
  21.  2.0    : Added support for tag functions. See the docs for details.
  22.     Author until this version:
  23.     Jochen Wiedmann
  24.     Am Eisteich 9
  25.     72555 Metzingen (Germany)
  26.     Tel. 07123 / 14881
  27.  2.1   19.08.96 : now made by SDI, added correct __MAXON__ support and
  28.     support for StormC++, added auto recognition of tagcall functions
  29.     changed the CLI interface completely
  30.  2.2   21.08.96 : fixed a lot of errors, added debug code
  31.  2.3   22.08.96 : little changes
  32.  2.4   24.08.96 : added proto-file creation
  33.  2.5   25.08.96 : added syscall and fix for functions ending in ...DMA
  34.  2.6   26.08.96 : fixed some errors, added CLIB parameter (used later for
  35.     CSTUBS)
  36.  2.7   01.09.96 : added correct Storm definition, added CLIB scan
  37.  2.8   02.09.96 : added assembler stub functions, added first ASM-stub code
  38.  2.9   04.09.96 : added Comment-Support
  39.  2.10  05.09.96 : changed CSTUB creation a bit
  40.  2.11  07.09.96 : speeded up output, reduced number of strndup calls
  41.  2.12  26.09.96 : pressing CTRL-C in early startup brought a wrong error
  42.     message - fixed
  43.  2.13  30.09.96 : made RegNames field to RegNames string - shorter Exe-file
  44.  2.14  01.10.96 : made SPECIAL 6 default, COMMENT also in LVO files
  45.  2.15  13.10.96 : corrected an error text
  46.  2.16  14.10.96 : added correct comment support and PRIVATE option
  47.  2.17  19.10.96 : now Maxon-compiled in Small data mode
  48.  2.18  22.10.96 : removed EXTERNC in Storm, Maxon and all pragmas, corrected
  49.     the texts, again SAS compiled
  50.  2.19  26.10.96 : added option to create FD files out of pragma files,
  51.     reworked a lot in the source
  52.  2.20  27.10.96 : fixed errors of previous version
  53.  2.21  28.10.96 : fixed error in CLIB scan
  54.  2.22  27.11.96 : SPECIAL numbers for lib and ASM code were wrong, removed
  55.     bug in Tag function stubs
  56.  2.23  06.12.96 : lib and stub creation still was wrong
  57.  2.24  31.12.96 : formed stub libs matching C++ file names, corrected CLIB
  58.     scan errors
  59.  2.25  04.01.97 : added HEADER option (I was asked for)
  60.  2.26  05.01.97 : added HEADER scan (in old file) and auto inserting
  61.  2.27  10.01.97 : stub functions missed register saving, outfuncs skip now,
  62.     when error occured (makes lots of error checking obsolete)
  63.  2.28  11.01.97 : forgot to add offset made by register saving
  64.  2.29  18.01.97 : now libtags and amitags defines only, when at least 1
  65.     tagfunc
  66.  2.30  13.02.97 : added local library base functions, rearranged SPECIAL
  67.           options, fixed some bugs
  68.  2.31  15.02.97 : corrected bugs inserted in previous version
  69.  2.32  16.02.97 : and again bug fixes, still didn't work
  70.  2.33  18.02.97 : corrected texts, added SPECIAL 28
  71.  2.34  25.03.97 : corrected Pragma --> FD file conversion, added ##shadow
  72.  2.35  26.03.97 : added STORMFD option, COMMENT, PRIVATE work again
  73.  2.36  29.03.97 : corrected *tagcall scan a bit
  74.  2.37  20.06.97 : added PASCAL stub lib production (SPECIAL 14, 15)
  75.  2.38  01.07.97 : fixed ##end handling
  76.  2.39  20.07.97 : added better proto file (__GNUC__ inline and pragma call),
  77.     removed C++ comments
  78.  2.40  24.11.97 : added new basenames to the list (devices and resources),
  79.     added tag-exception name checking (dos, utility libraries)
  80.  2.41  27.11.97 : fixed little bug with private functions, CSTUBS now
  81.     special option and no longer commandline arg, SPECIAL 10-15 got
  82.     numbers 11-16 (Sorry)
  83.  2.42  28.11.97 : Added two new warnings for CLIB
  84.  2.43  12.12.97 : faster FD file scan, one new warning
  85.  2.44  19.12.97 : fixed MODE settings for SPECIAL 15,16
  86.  2.45  30.01.98 : added function recognition, included inline creation,
  87.      inline stuff is based on fd2inline 1.11 (incomplete)
  88.  2.46  31.01.98 : continued inline stuff, fixed clib functions
  89.  2.47  05.02.98 : completed inline stuff, added alias names for dos functions
  90.  2.48  06.02.98 : changed Func interface - flags instead of tagmode
  91.  2.49  10.02.98 : fixed inline generation a bit, added SORTED argument,
  92.      RegNames got strings again
  93.  2.50  11.02.98 : bug-fixes, still did not work completely, hopefully got
  94.     all now
  95.  2.51  12.02.98 : and bug-fixes again :-(
  96.  2.52  15.02.98 : changed sorting order of arguments
  97.  2.53  20.02.98 : some code style changes
  98.  2.54  25.02.98 : added SMALLDATA model, removed 5 global variables (better
  99.     style), stub libs use MOVEM when possible, own MemRemember function
  100.  2.55  26.02.98 : bug fixes
  101.  2.56  15.03.98 : added FPU support
  102.  2.57  17.03.98 : added NOFPU keyword
  103.  2.58  19.03.98 : little fixes
  104.  2.59  20.03.98 : added enum and external type definitions defines
  105.  2.60  22.03.98 : added external types file scan
  106.  2.61  23.03.98 : fixed SAS flibcall, added FPU stubs
  107.  2.62  28.03.98 : bug fix with NOFPU and new option FPUONLY, total new clib
  108.     handling
  109.  2.63  29.03.98 : really lots of bug fixes, There are so much problems.
  110.     A better definition format would have been wonderful.
  111.  2.64  05.04.98 : bug fixes
  112.  2.65  07.04.98 : fixed Enforcer hit
  113.  2.66  08.04.98 : bug fix with type detection
  114.  2.67  20.04.98 : added GNU-only stuff
  115.  2.68  28.04.98 : SPECIAL 8 defaults to SAS-C names now
  116.  2.69  25.05.98 : added PowerUP stuff support
  117.  2.70  28.05.98 : added SAS PowerUP stuff, fixed error with function
  118.     detection in CLIB scan
  119.  2.71  30.05.98 : added PowerUP Inlines
  120.  2.72  12.06.98 : sorting turns of COMMENT now
  121.  2.73  05.07.98 : added first FPC stuff, added HEADER to PowerUP stuff,
  122.     added PASCAL header scan
  123.  2.74  06.07.98 : finished FPC stuff
  124.  2.75  07.07.98 : bug fixes for FPC stuff
  125.  2.76  09.07.98 : style changes for FPC stuff, bug fixes
  126.  2.77  11.07.98 : hopefully last FPC bug removed
  127.  2.78  23.07.98 : style changes and bug fixes for FPC stuff, more comments
  128.  2.79  10.08.98 : bug fix, when TO was used with a directory, clib got
  129.     wrong path if it was a relative path description
  130.  2.80  16.08.98 : now prints better error when filopen failed
  131.  2.81  26.10.98 : added BMAP files for BASIC, CODE needs to use large mode
  132.     now :-(
  133.  2.82  28.10.98 : optimizations and bug fixes
  134.  2.83  31.12.98 : fixed powerup stuff a bit
  135.  2.84  05.01.99 : fixed bug in Lib creation, when Dx/Ax and FPx were mixed
  136.  2.85  06.01.99 : added recognition of names ending in MESA, added notagcall
  137.     comment support, void functions no longer can be tagcall
  138.  2.86  10.01.99 : added BGUI special funcs, fixed bug in SPECIAL 42 code
  139.  2.87  12.01.99 : added asm-text (SECTION), moved 12-17 to 13-18
  140.  2.88  17.01.99 : better type detection, added some more basenames, some
  141.     little bug fixes, new makefile reduces file size a lot
  142.  2.89  17.07.99 : added union support
  143. */
  144.  
  145. #include <proto/exec.h>
  146. #include <proto/dos.h>
  147.  
  148. #include <exec/memory.h>
  149. #include <dos/doshunks.h>
  150.  
  151. #define SDI_TO_ANSI
  152. #include "SDI_ASM_STD_protos.h"
  153. #include "SDI_defines.h"
  154. #include "SDI_compiler.h"
  155.  
  156. #ifdef __MAXON__        /* needed for -gd option */
  157.   #include <linkerfunc.h>
  158. #endif
  159.  
  160. #define TEXT_SAS    "__SASC"    /* verified    */
  161. #define TEXT_SAS_60    "__SASC_60"    /* verified    */
  162. #define TEXT_MAXON    "__MAXON__"    /* verified    */
  163. #define TEXT_STORM    "__STORM__"    /* verified    */
  164. #define TEXT_DICE    "_DCC"        /* in 2.0 code    */
  165. #define TEXT_AZTEC    "AZTEC_C"    /* verified    */
  166. #define TEXT_GNUC    "__GNUC__"    /* verified    */
  167.  
  168. #define FLAG_EXTERNC    (1<< 0) /* add externc statements */
  169. #define FLAG_SYSCALL    (1<< 1)    /* create SAS-C syscall pragmas */
  170. #define FLAG_DOCOMMENT    (1<< 2) /* do comment processing */
  171. #define FLAG_PRIVATE    (1<< 3) /* also use private functions */
  172. #define FLAG_LOCALREG    (1<< 4) /* local file uses register call */
  173. #define FLAG_STORMFD    (1<< 5) /* FD file uses strange Storm format */
  174. #define FLAG_PASCAL    (1<< 6) /* library creation with PASCAL style */
  175. #define FLAG_SMALLDATA    (1<< 7) /* libraries use small data modell */
  176. #define FLAG_DONE    (1<< 8) /* destination file is not empty */
  177. #define FLAG_INLINENEW    (1<< 9) /* produce new style inlines */
  178. #define FLAG_INLINESTUB    (1<<10) /* produce stubs style inlines */
  179. #define FLAG_NOFPU    (1<<11) /* do not allow FPU registers */
  180. #define FLAG_DIDERROR    (1<<12) /* one error already printed, don't print 2nd */
  181. #define FLAG_FPUONLY    (1<<13) /* only use FPU registers */
  182. #define FLAG_GNUPRAG    (1<<14) /* insert inline call into pragma file */
  183. #define FLAG_POWERUP    (1<<15)    /* create Phase5 PowerUP files */
  184. #define FLAG_ASMSECTION (1<<16) /* create SECTIONS in Asm code */
  185.  
  186. #define FUNCFLAG_NORMAL    (1<<20) /* normal function */
  187. #define FUNCFLAG_TAG    (1<<21) /* a tagcall function */
  188. #define FUNCFLAG_ALIAS    (1<<22) /* an alias name for previous function */
  189.  
  190. /* Different modes the main program uses, one for each different file
  191.    type (except for those done with one function and flag settings). */
  192. #define MODUS_STUBTEXT      1
  193. #define MODUS_STUBCODE      2
  194. #define MODUS_LOCALDATA   3
  195. #define MODUS_PRAGMA      4
  196. #define MODUS_CSTUB      5
  197. #define MODUS_SASPOWER      6
  198. #define MODUS_PROTOPOWER  7
  199. #define MODUS_BMAP      8
  200. #define MODUS_LVO     10    /* and 11 and 12 and 13         */
  201. #define MODUS_PROTO     20    /* and 21 to 26                */
  202. #define MODUS_INLINE     30    /* and 31 and 32            */
  203. #define MODUS_PASCAL     40
  204. #define MODUS_ERROR    100
  205.  
  206. /* call types for CallFunc */
  207. #define TAGMODE_NORMAL    0    /* produce normal functions only */
  208. #define TAGMODE_TAGS    1    /* produce only tag functions */
  209. #define TAGMODE_BOTH    2    /* produce both types */
  210.  
  211. /* types specifiing name method for pragma creation */
  212. #define PRAGMODE_PRAGLIB    1
  213. #define PRAGMODE_PRAGSLIB    2
  214. #define PRAGMODE_PRAGSPRAGS    3
  215. #define PRAGMODE_NONE        4
  216.  
  217. #define BIAS_OFFSET    6  /* value to switch from one to next function */
  218.  
  219. #define EXTTYPESFILE    "FD2Pragma.types"
  220. #define EXTTYPESFILE2    "PROGDIR:FD2Pragma.types"
  221. #define FDFILEEXTENSION    "_lib.fd"
  222.  
  223. #define PARAM     "FROM=FDFILE/A,SPECIAL/N,MODE/N,"            \
  224.         "TO/K,CLIB/K,HEADER/K,"                    \
  225.         "AMICALL/K,LIBCALL/K,AMITAGS/K,LIBTAGS/K,"        \
  226.         "COMMENT/S,EXTERNC/S,FPUONLY/S,NOFPU/S,PRIVATE/S,"    \
  227.         "SMALLDATA/S,SORTED/S,STORMFD/S,USESYSCALL/S"
  228.  
  229. STRPTR RegNames[] = {
  230. "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  231. "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
  232. "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
  233. };
  234.  
  235. STRPTR RegNamesUpper[] = {
  236. "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
  237. "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
  238. "FP0", "FP1", "FP2", "FP3", "FP4", "FP5", "FP6", "FP7",
  239. };
  240.  
  241. enum Register_ID {
  242. REG_D0, REG_D1, REG_D2, REG_D3, REG_D4, REG_D5, REG_D6, REG_D7,
  243. REG_A0, REG_A1, REG_A2, REG_A3, REG_A4, REG_A5, REG_A6, REG_A7,
  244. REG_FP0, REG_FP1, REG_FP2, REG_FP3, REG_FP4, REG_FP5, REG_FP6, REG_FP7,
  245. MAXREG,
  246. };
  247. #define MAXREGNF    16 /* maximum register number without float regs */
  248.  
  249. struct Args
  250. {
  251.   STRPTR FDFILE;
  252.   ULONG* SPECIAL;
  253.   ULONG* MODE;
  254.   STRPTR TO;
  255.   STRPTR CLIB;
  256.   STRPTR HEADER;
  257.   STRPTR AMICALL;
  258.   STRPTR LIBCALL;
  259.   STRPTR AMITAGS;
  260.   STRPTR LIBTAGS;
  261.   ULONG  COMMENT;
  262.   ULONG  EXTERNC;
  263.   ULONG  FPUONLY;
  264.   ULONG  NOFPU;
  265.   ULONG  PRIVATE;
  266.   ULONG  SMALLDATA;
  267.   ULONG  SORTED;
  268.   ULONG  STORMFD;
  269.   ULONG  USESYSCALL;
  270. };
  271.  
  272. struct ShortList {
  273.   struct ShortList    *Next;
  274. };
  275.  
  276. struct ShortListRoot {
  277.   struct ShortList    *First;
  278.   struct ShortList    *Last;
  279.   ULONG         Size;
  280. };
  281.  
  282. #define AMIPRAGFLAG_PUBLIC    (1<<0)    /* is a public function */
  283. #define AMIPRAGFLAG_A6USE    (1<<1)    /* A6 is used for this function */
  284. #define AMIPRAGFLAG_A5USE    (1<<2)    /* A5 is used */
  285. #define AMIPRAGFLAG_A4USE    (1<<3)    /* A4 is used */
  286. #define AMIPRAGFLAG_D7USE    (1<<4)    /* D7 is used */
  287. #define AMIPRAGFLAG_ARGCOUNT    (1<<5)    /* when double args, ... */
  288. #define AMIPRAGFLAG_DIDWARN    (1<<6)    /* We printed a argcount warning */
  289. #define AMIPRAGFLAG_FLOATARG    (1<<7)    /* It has a float argument */
  290. #define AMIPRAGFLAG_NOCLIB    (1<<8)    /* No clib definition found */
  291. #define AMIPRAGFLAG_CLIBARGCNT    (1<<9)    /* CLIB argument count error */
  292.  
  293. struct AmiPragma {
  294.   struct ShortList        List;
  295.   UWORD             Bias;
  296.   UWORD                Line;
  297.   ULONG                Flags;
  298.   STRPTR            FuncName;
  299.   STRPTR            TagName;
  300.   struct Pragma_AliasNames *    AliasName;  /* possible second name */
  301.   UWORD             NumArgs;  /* register numbers */
  302.   UWORD                CallArgs; /* argument number in fd file */
  303.   struct AmiArgs
  304.   {
  305.     STRPTR            ArgName;
  306.     UWORD            ArgReg;
  307.   } Args[MAXREG];
  308. };
  309.  
  310. struct Comment {
  311.   struct ShortList    List;
  312.   STRPTR        Data;
  313.   UWORD         Bias;
  314. };
  315.  
  316. struct PragList {
  317.   struct ShortList    List;
  318.   struct ShortListRoot    Data;        /* contains list of PragData */
  319.   STRPTR        Basename;
  320. };
  321.  
  322. struct PragData {
  323.   struct ShortList    List;
  324.   struct ShortListRoot    Name;
  325.   ULONG         NumNames;
  326.   ULONG         Bias;
  327.   ULONG         NumArgs;
  328.   UBYTE         ArgReg[MAXREG];
  329. };
  330.  
  331. struct FDData {
  332.   STRPTR    Name;
  333.   STRPTR    Basename;
  334.   ULONG     Bias;
  335.   ULONG     Mode;        /* 0 = Normal, != 0 is TagName */
  336.   ULONG     NumArgs;
  337.   UBYTE     ArgReg[MAXREG];
  338. };
  339.  
  340. /* These CPP types match the strings used for CPP name creation. The
  341. defines are used both for name creation and type specification. */
  342. #define CPP_TYPE_VOID        'v'    /* void,    VOID    */
  343. #define CPP_TYPE_BYTE        'c'    /* char,    BYTE    */
  344. #define CPP_TYPE_WORD        's'    /* short,    WORD    */
  345. #define CPP_TYPE_LONG        'j'    /* long,    LONG    */
  346. #define CPP_TYPE_FLOAT        'f'    /* float,    FLOAT    */
  347. #define CPP_TYPE_DOUBLE     'd'    /* double,    DOUBLE    */
  348. #define CPP_TYPE_STRUCTURE    0
  349. #define CPP_TYPE_VARARGS    'e'
  350.  
  351. /* These types are for string creation only. */
  352. #define CPP_TYPE_ENUM        'E'
  353. #define CPP_TYPE_CONST        'C'
  354. #define CPP_TYPE_FUNCTION    'F'
  355. #define CPP_TYPE_POINTER    'P'
  356. #define CPP_TYPE_UNSIGNED    'U'
  357. #define CPP_TYPE_FUNCEND    'p'
  358. #define CPP_TYPE_REGISTER    'r'
  359.  
  360. /* Some flags to be used in CPP_NameType->Flags. */
  361. #define CPP_FLAG_UNSIGNED    (1<<0)    /* is an unsigned variable */
  362. #define CPP_FLAG_CONST        (1<<1)    /* type is const */
  363. #define CPP_FLAG_STRPTR     (1<<2)    /* this variable contains a STRPTR */
  364. #define CPP_FLAG_POINTER    (1<<3)    /* the variable is a pointer */
  365. #define CPP_FLAG_ENUM        (1<<4)    /* it is a enumeration */
  366. #define CPP_FLAG_STRUCT        (1<<5)    /* it is a structure */
  367. #define CPP_FLAG_UNION        (1<<6)    /* it is a union */
  368. #define CPP_FLAG_FUNCTION    (1<<7)    /* it is a function */
  369. #define CPP_FLAG_BOOLEAN    (1<<8)    /* in truth this element is bool */
  370. /* STRPTR is defined different under C and CPP -> I have to create two
  371. names, one time unsigned char *, one time signed char *, when somewhere
  372. a STRPTR occurs */
  373.  
  374. struct CPP_NameType { /* structure to describe a argument type */
  375.   STRPTR    StructureName;     /* if a structure or enum only  */
  376.   STRPTR    FuncArgs;     /* arguments of function - unterminated */
  377.   STRPTR    TypeStart;     /* start of this type         */
  378.   UWORD     StructureLength; /* length of the structure name */
  379.   UWORD        ArgsLength;     /* length of FuncArgs         */
  380.   UWORD        TypeLength;     /* length of this type         */
  381.   UWORD        FullLength;     /* length of complete type     */
  382.   UWORD     PointerDepth;     /* number of * in type      */
  383.   UWORD     Flags;         /* see above flags         */
  384.   UBYTE     Type;         /* see above defines         */
  385. };
  386.  
  387. struct ClibData { /* structure to describe data in CLIB file */
  388.   struct ClibData *    Next;          /* The next entry in this list */
  389.   STRPTR        FuncName;     /* name of the function */
  390.   ULONG            NumArgs;      /* number of arguments */
  391.   struct CPP_NameType    ReturnType;   /* data for return type */
  392.   struct CPP_NameType    Args[MAXREG]; /* data for argument types */
  393. };
  394.  
  395. struct CPP_ExternNames { /* structure for EXTTYPESFILE data */
  396.   struct CPP_ExternNames * Next;    /* The next entry in this list */
  397.   STRPTR           Type;    /* The unknown type */
  398.   struct CPP_NameType       NameType;    /* The replacement */
  399. };
  400.  
  401. struct CPP_TypeField { /* structure for internal defined types */
  402.   STRPTR    Text;    /* name of the type */ 
  403.   UWORD     Length; /* length of the name string */
  404.   UWORD     Flags;    /* CPP_FLAG flags */
  405.   UBYTE     Type;    /* CPP_TYPE value */
  406. };
  407.  
  408. struct Proto_LibTypes { /* structure to define structure type of base vars */
  409.   STRPTR    BaseName;    /* name of the library base */
  410.   STRPTR    StructureName;    /* name of the structure to be used */
  411. };
  412.  
  413. struct Pragma_ExecpNames { /* structure to specify special tagnames */
  414.   STRPTR    FunctionName;    /* function name */
  415.   STRPTR    TagName;    /* tag name to be used for this function */
  416. }; /* TagName 0 is valid as well to disable tagfunctions */
  417.  
  418. struct Pragma_AliasNames {
  419.   STRPTR    FunctionName;
  420.   STRPTR    AliasName;
  421.   ULONG        Type;
  422. };
  423.  
  424. #define NTP_NORMAL    0    /* no tags/args     */
  425. #define NTP_TAGS    1    /* TagFunction        */
  426. #define NTP_ARGS    2    /* ArgFunction        */
  427. #define NTP_UNKNOWN    3    /* CommentFunction    */
  428.  
  429. struct NameList {
  430.   struct ShortList    List;
  431.   ULONG         Type;    /* set by OptimizeFDData */
  432.   STRPTR        NormName;
  433.   STRPTR        PragName;
  434. };
  435.  
  436. struct InOut {
  437.   ULONG  file;
  438.   STRPTR pos;
  439.   STRPTR buf;
  440.   ULONG  size;
  441. };
  442.  
  443. struct RememberMem { /* structure for selfmade global memory list */
  444.   struct RememberMem *    rm_Next;    /* pointer to next entry */
  445.   ULONG            rm_Size;    /* entry size */
  446. };
  447.  
  448. struct RDArgs * rda            = 0;
  449. struct InOut    in            = {0,0,0,0},
  450.         out            = {0,0,0,5120};
  451. struct ClibData *    clibdata    = 0;
  452. struct FileInfoBlock *    fib        = 0;
  453. struct ShortListRoot    AmiPragma    = {0,0,sizeof(struct AmiPragma)},
  454.             Comment     = {0,0,sizeof(struct Comment)};
  455. struct RememberMem *    remember    = 0;
  456. struct CPP_ExternNames *extnames    = 0;
  457. ULONG        oldfh            = 0;
  458. ULONG        lock            = 0;
  459. STRPTR        BaseName        = 0;
  460. STRPTR        ShortBaseName        = 0;
  461. STRPTR        ShortBaseNameUpper    = 0;
  462. ULONG        DosVersion        = 37; /* force OS2.0 */
  463. STRPTR        HEADER            = 0;
  464. ULONG        headersize        = 0;
  465. ULONG        Flags            = 0;
  466. ULONG        Output_Error        = 1; /* Output error occured when 0 */
  467. ULONG        tagfuncs        = 0; /* are there some tagfuncs in FD */
  468.  
  469. /* Prototypes for the functions */
  470. STRPTR DupString(STRPTR, ULONG);
  471. STRPTR AllocListMem(ULONG);
  472. void FreeListMem(void);
  473. STRPTR SkipBlanks(STRPTR);
  474. STRPTR SkipBlanksRet(STRPTR);
  475. STRPTR SkipName(STRPTR);
  476. STRPTR GetBaseType(void);
  477. ULONG  CloseDest(STRPTR);
  478. ULONG  MakeTagFunction(struct AmiPragma *);
  479. void   MakeLines(STRPTR, ULONG);
  480. ULONG  SpecialFuncs(void);
  481. void   SortFDList(void);
  482. ULONG  ScanFDFile(void);
  483. LONG   ScanTypes(STRPTR, ULONG);
  484. void   FindHeader(void);
  485. ULONG  GetRegisterData(struct AmiPragma *);
  486. UWORD  GetFRegisterData(struct AmiPragma *);
  487. ULONG  OutputXDEF(STRPTR, ...);
  488. UWORD *AsmStackCopy(UWORD *, struct AmiPragma *, ULONG, ULONG);
  489. /* ------------------------------------------------------------------ */
  490. void   DoError(UBYTE, ULONG, ...);
  491. ULONG  Out(ULONG);
  492. ULONG  DoOutput(STRPTR, ...);
  493. ULONG  DoOutputDirect(APTR, ULONG);
  494. /* ------------------------------------------------------------------ */
  495. struct ShortList *NewItem(struct ShortListRoot *);
  496. struct ShortList *RemoveItem(struct ShortListRoot *, struct ShortList *);
  497. void          AddItem(struct ShortListRoot *, struct ShortList *);
  498. /* ------------------------------------------------------------------ */
  499. typedef ULONG (*FuncType)(struct AmiPragma *, ULONG, STRPTR);
  500.  
  501. ULONG FuncAMICALL(struct AmiPragma *, ULONG, STRPTR);
  502. ULONG FuncLIBCALL(struct AmiPragma *, ULONG, STRPTR);
  503. ULONG FuncAsmText(struct AmiPragma *, ULONG, STRPTR);
  504. ULONG FuncAsmCode(struct AmiPragma *, ULONG, STRPTR);
  505. ULONG FuncCSTUBS (struct AmiPragma *, ULONG, STRPTR);
  506. ULONG FuncLVOXDEF(struct AmiPragma *, ULONG, STRPTR);
  507. ULONG FuncLVO     (struct AmiPragma *, ULONG, STRPTR);
  508. ULONG FuncLocCode(struct AmiPragma *, ULONG, STRPTR);
  509. ULONG FuncLocText(struct AmiPragma *, ULONG, STRPTR);
  510. ULONG FuncInline (struct AmiPragma *, ULONG, STRPTR);
  511. ULONG FuncPowerUP(struct AmiPragma *, ULONG, STRPTR);
  512. ULONG FuncFPCUnit(struct AmiPragma *, ULONG, STRPTR);
  513. ULONG FuncFPCType(struct AmiPragma *, ULONG, STRPTR);
  514. ULONG FuncBMAP   (struct AmiPragma *, ULONG, STRPTR);
  515. ULONG CallFunc(ULONG, STRPTR, FuncType);
  516. /* ------------------------------------------------------------------ */
  517. LONG   AddClibEntry(STRPTR, STRPTR, ULONG);
  518. LONG   ScanClibFile(STRPTR, STRPTR);
  519. LONG   IsCPPType(struct CPP_NameType *, UBYTE);
  520. LONG   GetCPPType(struct CPP_NameType *, STRPTR);
  521. struct ClibData *GetClibFunc(STRPTR, struct AmiPragma *, ULONG);
  522. LONG   CheckKeyword(STRPTR, STRPTR, LONG);
  523. ULONG  CopyCPPType(STRPTR, ULONG, struct ClibData *, struct AmiArgs *);
  524. ULONG  OutClibType(struct CPP_NameType *, STRPTR);
  525. ULONG  OutPASCALType(struct CPP_NameType *, STRPTR, ULONG);
  526. /* ------------------------------------------------------------------ */
  527. ULONG CallPrag(ULONG, STRPTR, FuncType);
  528. ULONG CreatePragmaFile(STRPTR, STRPTR, STRPTR, STRPTR, ULONG);
  529. ULONG CreateCSTUBSFile(void);
  530. ULONG CreateLVOFile(ULONG);
  531. ULONG CreateAsmStubs(ULONG, ULONG);
  532. ULONG CreateProtoFile(ULONG);
  533. ULONG CreateLocalData(STRPTR, ULONG, STRPTR, ULONG);
  534. ULONG CreateInline(ULONG);
  535. ULONG CreateSASPowerUP(void);
  536. ULONG CreateProtoPowerUP(void);
  537. ULONG CreateFPCUnit();
  538. ULONG CreateBMAP();
  539. /* ------------------------------------------------------------------ */
  540. ULONG GetName(struct NameList *, struct ShortListRoot *, ULONG);
  541. ULONG MakeFD(struct PragList *);
  542. void  OptimizeFDData(struct PragData *);
  543. UBYTE GetHexValue(UBYTE);
  544. UBYTE GetDoubleHexValue(UBYTE *);
  545. ULONG AddFDData(struct ShortListRoot *, struct FDData *);
  546. ULONG GetLibData(struct FDData *);
  547. ULONG GetFlibData(struct FDData *);
  548. ULONG GetAmiData(struct FDData *);
  549. ULONG CreateFDFile(STRPTR);
  550. /* ------------------------------------------------------------------ */
  551. void main(void);
  552. void End(ULONG);
  553.  
  554. enum {
  555. ERR_TAGFUNC_NEEDS_ARGUMENT,
  556. ERR_CANNOT_CONVERT_PRAGMA_TAGCALL,
  557. ERR_TAG_DEF_WITHOUT_PRAGMA,
  558. ERR_BASENAME_DECLARED_TWICE,
  559. ERR_EXPECTED_SLASH_IN_BASENAME,
  560. ERR_EXPECTED_BASENAME,
  561. ERR_EXPECTED_BIAS_VALUE,
  562. ERR_ASSUMING_POSITIVE_BIAS_VALUE,
  563. ERR_MISSING_FUNCTION_NAME,
  564. ERR_EXPECTED_OPEN_BRACKET,
  565. ERR_TO_MUCH_ARGUMENTS,
  566. ERR_EXPECTED_ARGUMENT_NAME,
  567. ERR_EXPECTED_CLOSE_BRACKET,
  568. ERR_EXPECTED_REGISTER_NAME,
  569. ERR_A7_NOT_ALLOWED,
  570. ERR_REGISTER_USED_TWICE,
  571. ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER,
  572. ERR_ASSUMING_BIAS_OF_30,
  573. ERR_EXTRA_CHARACTERS,
  574. ERR_MISSING_BASENAME,
  575. ERR_WRITING_FILE,
  576. ERR_EXPECTED_COMMA,
  577. ERR_DIFFERENT_TO_PREVIOUS,
  578. ERR_UNKNOWN_VARIABLE_TYPE,
  579. ERR_UNKNOWN_ERROR,
  580. ERR_MISSING_END,
  581. ERR_PROTOTYPE_MISSING,
  582. ERR_NOPROTOTYPES_FILE,
  583. ERR_UNKNOWN_DIRECTIVE,
  584. ERR_INLINE_A4_AND_A5,
  585. ERR_INLINE_D7_AND_A45,
  586. ERR_MISSING_SHORTBASENAME,
  587. ERR_USER_ABORT,
  588. ERR_A6_NOT_ALLOWED,
  589. ERR_EMPTY_FILE,
  590. ERR_FLOATARG_NOT_ALLOWED,
  591. ERR_WRONG_TYPES_LINE,
  592. ERR_LONG_DOUBLE,
  593. ERR_CLIB_ARG_COUNT,
  594. ERR_OPEN_FILE,
  595. ERR_A5_NOT_ALLOWED,
  596. };
  597.  
  598. struct ErrField {
  599.   UBYTE  Type;    /* 0 = Error, 1 = Warning */
  600.   UBYTE  Skip;
  601.   STRPTR Error;
  602. } Errors[] = {
  603. {1, 1, "Tag function must have arguments."},
  604. {1, 1, "Cannot convert pragma name into tag name."},
  605. {1, 1, "Tag definition without preceding Pragma."},
  606. {1, 0, "Basename declared twice."},
  607. {1, 0, "Expected preceding _ in Basename."},
  608. {1, 1, "Expected Basename."},
  609. {1, 0, "Expected Bias value."},
  610. {1, 0, "Assuming positive bias value."},
  611. {1, 1, "Missing function name."},
  612. {1, 1, "Expected '('."},
  613. {1, 1, "Too much arguments."},
  614. {1, 1, "Expected argument name."},
  615. {1, 1, "Expected ')'."},
  616. {1, 1, "Expected register name."},
  617. {1, 1, "A7 not allowed as argument register."},
  618. {1, 1, "Register used twice."},
  619. {1, 0, "Number of arguments != number of registers."},
  620. {1, 0, "Assuming bias of 30."},
  621. {1, 1, "Extra characters."},
  622. {0, 0, "Missing Basename in FD file."},
  623. {0, 0, "Failed to write destination file."},
  624. {1, 1, "Expected ','."},
  625. {0, 1, "Data different to previous given."},
  626. {1, 0, "Unknown type of argument %ld."},
  627. {0, 0, "Unknown problem: program error or corrupt input data."},
  628. {1, 0, "Missing ##end."},
  629. {1, 0, "Prototype for function \"%s\" not found."},
  630. {0, 0, "No prototypes file (CLIB parameter) was specified."},
  631. {1, 1, "Unknown directive '##%s' found."},
  632. {1, 0, "Usage of both A4 and A5 is not supported."},
  633. {1, 0, "Usage of both D7 and A4 or A5 is not supported."},
  634. {0, 0, "Missing Basename in FD file and FD filename."},
  635. {0, 0, "User aborted operation."},
  636. {1, 0, "A6 not allowed as argument register."},
  637. {1, 0, "Empty or partial file deleted."},
  638. {1, 1, "Floating point arguments not allowed."},
  639. {0, 0, "Wrong definition in external type definition file."},
  640. {1, 0, "Cannot determine if FPU argument is double or single."},
  641. {1, 0, "CLIB argument count differs for %s (%ld != %ld)."},
  642. {0, 0, "Could not open file \"%s\"."},
  643. {1, 0, "A5 cannot be used as argument register."},
  644. };
  645.  
  646. struct CPP_TypeField CPP_Field[] = {
  647. {"long",    4, 0,            CPP_TYPE_LONG},
  648. {"ULONG",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  649. {"LONGBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  650. {"CPTR",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  651. {"Tag",     3, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  652. {"Object",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_LONG},
  653. {"LONG",    4, 0,            CPP_TYPE_LONG},
  654. {"BPTR",    4, 0,            CPP_TYPE_LONG},
  655. {"BSTR",    4, 0,            CPP_TYPE_LONG},
  656. {"short",    5, 0,            CPP_TYPE_WORD},
  657. {"CxObj",    5, 0,            CPP_TYPE_LONG},
  658. {"CxMsg",    5, 0,            CPP_TYPE_LONG},
  659. {"USHORT",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  660. {"UWORD",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  661. {"UCOUNT",    6, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  662. {"WORDBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  663. {"RPTR",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_WORD},
  664. {"SHORT",    5, 0,            CPP_TYPE_WORD},
  665. {"COUNT",    5, 0,            CPP_TYPE_WORD},
  666. {"WORD",    4, 0,            CPP_TYPE_WORD},
  667. {"BOOL",    4, CPP_FLAG_BOOLEAN,    CPP_TYPE_WORD},
  668. {"char",    4, 0,            CPP_TYPE_BYTE},
  669. {"UBYTE",    5, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  670. {"TEXT",    4, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  671. {"BYTEBITS",    8, CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  672. {"BYTE",    4, 0,            CPP_TYPE_BYTE},
  673. {"void",    4, 0,            CPP_TYPE_VOID},
  674. {"VOID",    4, 0,            CPP_TYPE_VOID},
  675. {"float",    5, 0,            CPP_TYPE_FLOAT},
  676. {"FLOAT",    5, 0,            CPP_TYPE_FLOAT},
  677. {"double",    6, 0,            CPP_TYPE_DOUBLE},
  678. {"DOUBLE",    6, 0,            CPP_TYPE_DOUBLE},
  679. {"STRPTR",    6, CPP_FLAG_POINTER|CPP_FLAG_STRPTR|CPP_FLAG_UNSIGNED,
  680.                     CPP_TYPE_BYTE},
  681. {"APTR",    4, CPP_FLAG_POINTER,    CPP_TYPE_VOID},
  682. {"ClassID",    7, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  683. {"PLANEPTR",    8, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,    CPP_TYPE_BYTE},
  684. {"DisplayInfoHandle",17,CPP_FLAG_POINTER,CPP_TYPE_VOID},
  685. {0,0,0,0},
  686. };
  687.  
  688. struct Proto_LibTypes Proto_LibTypes[] = {
  689. {"DOSBase",            "DosLibrary"},
  690. {"SysBase",            "ExecBase"},
  691. {"ExpansionBase",        "ExpansionBase"},
  692. {"GfxBase",            "GfxBase"},
  693. {"IntuitionBase",        "IntuitionBase"},
  694. {"LocaleBase",            "LocaleBase"},
  695. {"MathIeeeDoubBasBase",     "MathIEEEBase"},
  696. {"MathIeeeDoubTransBase",    "MathIEEEBase"},
  697. {"MathIeeeSingBasBase",     "MathIEEEBase"},
  698. {"MathIeeeSingTransBase",    "MathIEEEBase"},
  699. {"RealTimeBase",        "RealTimeBase"},
  700. {"RexxSysBase",         "RxsLib"},
  701. {"UtilityBase",         "UtilityBase"},
  702. /* resources - The Node entries may be correct, but I don't know it. */
  703. /*    {"BattClockBase",        "Node"}, */
  704. /*    {"BattMemBase",            "Node"}, */
  705. {"DiskBase",            "DiskResource"},
  706. /*    {"MiscBase",            "Node"}, */
  707. /*    {"PotgoBase",            "Node"}, */
  708. /* devices */
  709. {"ConsoleDevice",        "Device"},
  710. {"InputBase",            "Device"},
  711. {"RamdriveDevice",        "Device"},
  712. {"TimerBase",            "Device"},
  713. /* non default Basenames */
  714. {"DatamasterBase",        "DatamasterBase"},
  715. {"PPBase",            "PPBase"},
  716. {"ReqToolsBase",        "ReqToolsBase"},
  717. {"UnpackBase",            "UnpackLibrary"},
  718. {"xfdMasterBase",        "xfdMasterBase"},
  719. {"xadMasterBase",        "xadMasterBase"},
  720. {"xvsBase",            "xvsBase"},
  721. {"GTXBase",            "GTXBase"},
  722. {"ArpBase",            "ArpBase"},
  723. {0, 0},
  724. };
  725.  
  726. /* CachePostDMA, CachePreDMA are done by #?DMA check */
  727. struct Pragma_ExecpNames Pragma_ExecpNames[] = {
  728. {"VFWritef",            "FWritef"},
  729. {"VFPrintf",            "FPrintf"},
  730. {"VPrintf",            "Printf"},
  731. /* {"RefreshDTObjectA",        "RefreshDTObjects"}, */
  732. {"ReadArgs",            0},
  733. {"FreeArgs",            0},
  734. {"CloneTagItems",        0},
  735. {"FindTagItem",            0},
  736. {"FreeTagItems",        0},
  737. {"GetTagData",            0},
  738. {"PackBoolTags",        0},
  739. {"PackStructureTags",        0},
  740. {"UnpackStructureTags",        0},
  741. {"BGUI_PackStructureTags",    0},
  742. {"BGUI_UnpackStructureTags",    0},
  743. {0,0},
  744. };
  745.  
  746. /* for double tagcall names (currently only necessary for dos.library) */
  747. struct Pragma_AliasNames Pragma_AliasNames[] = {
  748. {"AllocDosObject",    "AllocDosObjectTagList",    FUNCFLAG_NORMAL},
  749. {"CreateNewProc",    "CreateNewProcTagList",        FUNCFLAG_NORMAL},
  750. {"NewLoadSeg",        "NewLoadSegTagList",        FUNCFLAG_NORMAL},
  751. {"SystemTagList",    "System",            FUNCFLAG_NORMAL},
  752. {0,0,0},
  753. };
  754.  
  755. /* special names, which get an x before name in BMAP files */
  756. STRPTR BMAPSpecial[] =
  757. {"abs", "Close", "Exit", "Input", "Open", "Output", "Read", "tan",
  758. "Translate", "Wait", "Write", 0};
  759.  
  760.  
  761. STRPTR DupString(STRPTR Str, ULONG Len)
  762. {
  763.   STRPTR res;
  764.   if((res = AllocListMem(Len+1)))
  765.   {
  766.     CopyMem(Str, res, Len);
  767.     res[Len] = '\0';
  768.   }
  769.   return res;
  770. }
  771.  
  772. STRPTR AllocListMem(ULONG size)
  773. {
  774.   struct RememberMem *r;
  775.  
  776.   size += sizeof(struct RememberMem);
  777.  
  778.   if((r = (struct RememberMem *) AllocMem(size, MEMF_ANY|MEMF_CLEAR)))
  779.   {
  780.     r->rm_Next = remember;
  781.     r->rm_Size = size;
  782.     remember = r;
  783.     return ((STRPTR) r)+sizeof(struct RememberMem);
  784.   }
  785.   return 0;
  786. }
  787.  
  788. void FreeListMem(void)
  789. {
  790.   struct RememberMem *r;
  791.  
  792.   r = remember;
  793.  
  794.   while(r)
  795.   {
  796.     struct RememberMem *s;
  797.     s = r;
  798.     r = r->rm_Next;
  799.     
  800.     FreeMem(s, s->rm_Size);
  801.   }
  802. }
  803.  
  804. STRPTR SkipBlanks(STRPTR OldPtr)
  805. {
  806.   while(*OldPtr == ' ' || *OldPtr == '\t')
  807.     ++OldPtr;
  808.   return OldPtr;
  809. }
  810.  
  811. STRPTR SkipBlanksRet(STRPTR OldPtr)
  812. {
  813.   while(*OldPtr == ' ' || *OldPtr == '\t' || *OldPtr == '\n')
  814.     ++OldPtr;
  815.   return OldPtr;
  816. }
  817.  
  818. /*
  819.     This function is used to skip over variable names.
  820.  
  821.     Inputs: OldPtr  - pointer to the beginning of a string.
  822.  
  823.     Result: Pointer to the first character of the string, that is not one
  824.         of a-z, A-Z, 0-9 or the underscore.
  825. */
  826.  
  827. STRPTR SkipName(STRPTR OldPtr)
  828. {
  829.   while(isalnum(*OldPtr) || *OldPtr == '_')
  830.     ++OldPtr;
  831.   return OldPtr;
  832. }
  833.  
  834. STRPTR GetBaseType(void)
  835. {
  836.   ULONG i;
  837.   STRPTR str = "Library";
  838.  
  839.   for(i = 0; BaseName && Proto_LibTypes[i].BaseName; ++i)
  840.   {
  841.     if(!(strcmp(Proto_LibTypes[i].BaseName, BaseName)))
  842.     {
  843.       str = Proto_LibTypes[i].StructureName; break;
  844.     }
  845.   }
  846.   return str;
  847. }
  848.  
  849. ULONG CloseDest(STRPTR name)
  850. {
  851.   if(out.file)
  852.   {
  853.     Out(out.size);    /* clears Output-Buffer */
  854.     Close(out.file);
  855.     out.file = 0;
  856.  
  857.     if(!(Flags & FLAG_DONE) || !Output_Error || CTRL_C)
  858.     {
  859.       DoError(ERR_EMPTY_FILE, 0);
  860.       DeleteFile(name); return 0;
  861.     }
  862.     Flags &= ~FLAG_DONE;    /* clear the flag */
  863.   }
  864.   else
  865.     return 0;
  866.   return 1;
  867. }
  868.  
  869. ULONG MakeTagFunction(struct AmiPragma *ap)
  870. {
  871.   ULONG len = strlen(ap->FuncName), i=0;
  872.  
  873. #ifdef DEBUG_OLD
  874.   VPrintf("MakeTagFunction:\n", 0);
  875. #endif
  876.  
  877.   if(!ap->NumArgs)
  878.     return 1;
  879.  
  880.   ++tagfuncs;
  881.  
  882.   while(Pragma_ExecpNames[i].FunctionName && /* check the exception names */
  883.   strcmp(ap->FuncName, Pragma_ExecpNames[i].FunctionName))
  884.     ++i;
  885.  
  886.   if(Pragma_ExecpNames[i].FunctionName)
  887.   {
  888.     if(!(ap->TagName = Pragma_ExecpNames[i].TagName));
  889.       --tagfuncs;
  890.   }
  891.   else if(ap->FuncName[len-1] == 'A')
  892.   {
  893.     if(!strcmp(ap->FuncName+len-3, "DMA") ||
  894.     !strcmp(ap->FuncName+len-4, "MESA")) /* skip names with DMA or MESA at end */
  895.     { --tagfuncs; return 1;}
  896.     if(!(ap->TagName = DupString(ap->FuncName, len-1)))
  897.       return 0;
  898.   }
  899.   else if(!strcmp(ap->FuncName + len-7, "TagList"))
  900.   {
  901.     if(!(ap->TagName = DupString(ap->FuncName, len-3)))
  902.       return 0;
  903.     ap->TagName[len-4] = 's';
  904.   }
  905.   else if(!strcmp(ap->FuncName + len-4, "Args"))
  906.   {
  907.     if(!(ap->TagName = DupString(ap->FuncName, len-4)))
  908.       return 0;
  909.   }
  910.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "tags") ||
  911.   !stricmp(ap->Args[ap->NumArgs-1].ArgName, "taglist"))
  912.   {
  913.     if(!(ap->TagName = DupString(ap->FuncName, len+4)))
  914.       return 0;
  915.     CopyMem("Tags", ap->TagName + len, 5);
  916.   }
  917.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "args"))
  918.   {
  919.     if(!(ap->TagName = DupString(ap->FuncName, len+4)))
  920.       return 0;
  921.     CopyMem("Args", ap->TagName + len, 5);
  922.   }
  923.   else
  924.     --tagfuncs; /* not a tagfunction, incrementing was false, undo it */
  925.  
  926.   return 1;
  927. }
  928.  
  929. void MakeLines(STRPTR buffer, ULONG size)
  930. {
  931.   if(size && buffer)
  932.   {
  933.     /* make a real C++ zero string ending line */
  934.     while(--size)
  935.     {
  936.       if(*buffer == '\n')
  937.         *buffer = '\0';
  938.       ++buffer;
  939.     }
  940.     *buffer = '\0';
  941.   }
  942. }
  943.  
  944. /* Do any special functions, which cannot be done with other exception
  945.    stuff - currently only dos.library DoPkt function. */
  946. ULONG SpecialFuncs(void)
  947. {
  948.   struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
  949.  
  950.   if(ap->Bias == 0xF0 && !strcmp("DoPkt", ap->FuncName))
  951.   {
  952.     struct AmiPragma *d;
  953.     ULONG i;
  954.  
  955.     for(i = 0; i < 5; ++i)
  956.     {
  957.       if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  958.     return 0;
  959.       CopyMem(ap, d, sizeof(struct AmiPragma));
  960.       d->FuncName = DupString(ap->FuncName, 6);
  961.       d->FuncName[5] = '0'+i;
  962.       d->NumArgs = d->CallArgs = i + 2;
  963.       AddItem(&AmiPragma, (struct ShortList *) d);
  964.     }
  965.   }
  966.   return 1;
  967. }
  968.  
  969. void SortFDList(void)
  970. {
  971.   struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.First, *ap2, *ap3;
  972.   AmiPragma.First = AmiPragma.Last = 0;
  973.  
  974.   while(ap)
  975.   {
  976.     ap3 = 0;
  977.     ap2 = (struct AmiPragma *) AmiPragma.First;
  978.  
  979.     /* for FD2Inline style we need to use strcmp instead of stricmp here */
  980.     while(ap2 && stricmp(ap2->FuncName, ap->FuncName) < 0)
  981.     {
  982.       ap3 = ap2;
  983.       ap2 = (struct AmiPragma *) ap2->List.Next;
  984.     }
  985.  
  986.     ap2 = ap;
  987.     ap = (struct AmiPragma *) ap->List.Next;
  988.  
  989.     if(ap3)
  990.     {
  991.       ap2->List.Next = (struct ShortList *) ap3->List.Next;
  992.       ap3->List.Next = (struct ShortList *) ap2;
  993.     }
  994.     else
  995.     {
  996.       ap2->List.Next = AmiPragma.First;
  997.       AmiPragma.First = (struct ShortList *) ap2;
  998.     }
  999.     if(ap && !ap->List.Next)
  1000.       AmiPragma.Last = (struct ShortList *) ap2;
  1001.   }
  1002. }
  1003.  
  1004. ULONG ScanFDFile(void)
  1005. {
  1006. #ifdef DEBUG_OLD
  1007.   VPrintf("ScanFDFile:\n", 0);
  1008. #endif
  1009.  
  1010.   ULONG _public = 1;
  1011.   LONG bias = -1;
  1012.   ULONG linenum, len;
  1013.   ULONG actcom = 0;
  1014.  
  1015.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  1016.   {
  1017.     if(*in.pos == '*')         /*  Comment   */
  1018.     {
  1019.       STRPTR oldpos = in.pos;
  1020. #ifdef DEBUG_OLD
  1021.   VPrintf("ScanFDFile: found a comment\n", 0);
  1022. #endif
  1023.       in.pos = SkipBlanks(in.pos+1);
  1024.       if(!strnicmp(in.pos, "notagcall", 9))
  1025.       {
  1026.     struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
  1027.         
  1028.         if(ap->TagName)
  1029.         {
  1030.           --tagfuncs; ap->TagName = 0;
  1031.         }
  1032.     in.pos = SkipBlanks(in.pos + 9);
  1033.       }
  1034.       else if(!strnicmp(in.pos, "tagcall", 7))  /*  Tag to create?  */
  1035.       {
  1036.     struct AmiPragma *prevpragma = (struct AmiPragma *)
  1037.         AmiPragma.Last;
  1038.  
  1039.     in.pos = SkipBlanks(in.pos + 7);
  1040.     if(!prevpragma)
  1041.     {
  1042.       DoError(ERR_TAG_DEF_WITHOUT_PRAGMA, linenum);
  1043.       ++in.pos;
  1044.       continue;
  1045.     }
  1046.  
  1047.     if(!prevpragma->NumArgs)
  1048.     {
  1049.       DoError(ERR_TAGFUNC_NEEDS_ARGUMENT, linenum);
  1050.       ++in.pos;
  1051.       continue;
  1052.     }
  1053.  
  1054.     /* Get the tag functions name. */
  1055.  
  1056.     if(!prevpragma->TagName && (_public || (Flags & FLAG_PRIVATE)))
  1057.       ++tagfuncs;
  1058.  
  1059.     if(*in.pos)
  1060.     {
  1061.       STRPTR oldptr, tptr = prevpragma->TagName;
  1062.  
  1063.       len = strlen(prevpragma->FuncName)+strlen(in.pos)+1;
  1064.       if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len)))
  1065.         return 0;
  1066.  
  1067.       if(*in.pos == '-')
  1068.       {
  1069.         STRPTR removeptr;
  1070.  
  1071.         oldptr = in.pos = SkipBlanks(in.pos+1);
  1072.         in.pos = SkipName(in.pos);
  1073.         if((len = in.pos-oldptr))
  1074.         {
  1075.           removeptr = prevpragma->TagName+strlen(prevpragma->TagName)-len;
  1076.           if(strncmp(removeptr, oldptr, len))
  1077.           {
  1078. #ifdef DEBUG_OLD
  1079.   {
  1080.     struct data {STRPTR a;STRPTR b;ULONG c;} a;
  1081.     a.a = removeptr;
  1082.     a.b = oldptr;
  1083.     a.c = len;
  1084.     VPrintf("ScanFDFile: *tagcall -: %s, %s, %ld\n", &a);
  1085.   }
  1086. #endif
  1087.         DoError(ERR_CANNOT_CONVERT_PRAGMA_TAGCALL, linenum);
  1088.         prevpragma->TagName = tptr;
  1089.         ++in.pos;
  1090.         continue;
  1091.           }
  1092.  
  1093.           *removeptr = '\0';
  1094.         }
  1095.         in.pos = SkipBlanks(in.pos);
  1096.       }
  1097.       if(*in.pos == '+')
  1098.         in.pos = SkipBlanks(in.pos+1);
  1099.       else
  1100.         *in.pos = toupper(*in.pos);
  1101.  
  1102.       in.pos = SkipName((oldptr = in.pos));
  1103.       len = in.pos-oldptr;
  1104.       if(len)
  1105.       {
  1106.         ULONG a = strlen(prevpragma->TagName);
  1107.         CopyMem(oldptr, prevpragma->TagName+a, len);
  1108.         prevpragma->TagName[a+len] = '\0';
  1109.       }
  1110.     }
  1111.     else if(!prevpragma->TagName)
  1112.     {
  1113.       len = strlen(prevpragma->FuncName);
  1114.       if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len+4)))
  1115.         return 0;
  1116.       CopyMem("Tags", prevpragma->TagName + len, 5);
  1117.     }
  1118.       }
  1119.       else
  1120.       {
  1121.     if(actcom)
  1122.       *(oldpos-1) = '\n';
  1123.     else if(Flags & FLAG_DOCOMMENT)
  1124.     {
  1125.       struct Comment *d;
  1126.       if(!(d = (struct Comment *) NewItem(&Comment)))
  1127.         return 0;
  1128.       d->Bias = bias;
  1129.       d->Data = oldpos;
  1130.       AddItem(&Comment, (struct ShortList *) d);
  1131.       actcom = 1;
  1132.     }
  1133.     while(*in.pos)
  1134.       ++in.pos;
  1135.       }
  1136.     }
  1137.     else if(*in.pos == '#' && in.pos[1] == '#')
  1138.     {
  1139.       in.pos += 2;
  1140.       actcom = 0; /* no Comment */
  1141.  
  1142.       if(!strnicmp(in.pos, "base", 4))
  1143.       {
  1144. #ifdef DEBUG_OLD
  1145.   VPrintf("ScanFDFile: found ##base\n", 0);
  1146. #endif
  1147.         STRPTR oldptr;
  1148.  
  1149.         if(BaseName)
  1150.       DoError(ERR_BASENAME_DECLARED_TWICE, linenum);
  1151.  
  1152.         in.pos = SkipBlanks(in.pos+4);
  1153.         if(*in.pos != '_')
  1154.       DoError(ERR_EXPECTED_SLASH_IN_BASENAME, linenum);
  1155.         else
  1156.       ++in.pos;
  1157.  
  1158.         in.pos = SkipName((oldptr = in.pos));
  1159.         if((len = in.pos-oldptr))
  1160.         {
  1161.       if(!(BaseName = DupString(oldptr, len)))
  1162.         return 0;
  1163.       if(!ShortBaseName && !(ShortBaseName = DupString(BaseName, len-4)))
  1164.         return 0;
  1165.         }
  1166.         else
  1167.       DoError(ERR_EXPECTED_BASENAME, linenum);
  1168.       }
  1169.       else if(!strnicmp(in.pos, "bias", 4))
  1170.       {
  1171. #ifdef DEBUG_OLD
  1172.   VPrintf("ScanFDFile: found ##bias\n", 0);
  1173. #endif
  1174.         STRPTR ptr;
  1175.         LONG newbias;
  1176.  
  1177.         in.pos += 5;
  1178.         newbias = strtol(in.pos, &ptr, 10);
  1179.         if(ptr == in.pos)
  1180.       DoError(ERR_EXPECTED_BIAS_VALUE, linenum);
  1181.         else if(newbias < 0)
  1182.         {
  1183.       DoError(ERR_ASSUMING_POSITIVE_BIAS_VALUE, linenum);
  1184.       bias = -newbias;
  1185.         }
  1186.         else
  1187.       bias = newbias;
  1188.         in.pos = SkipName(in.pos);
  1189.       }
  1190.       else if(!strnicmp(in.pos, "end", 3))
  1191.       {
  1192.         bias = 0; break;
  1193.       }
  1194.       else if(!strnicmp(in.pos, "shadow", 6)) /* introduced by Storm */
  1195.       {
  1196.         in.pos += 6;
  1197.         bias -= BIAS_OFFSET;
  1198.       }
  1199.       else if(!strnicmp(in.pos, "public", 6))
  1200.       {
  1201.         in.pos += 6;
  1202.         _public = 1;
  1203.       }
  1204.       else if(!strnicmp(in.pos, "private", 7))
  1205.       {
  1206.         in.pos += 7;
  1207.         _public = 0;
  1208.       }
  1209.       else
  1210.         DoError(ERR_UNKNOWN_DIRECTIVE, linenum, in.pos);
  1211.     }
  1212.     else
  1213.     {
  1214. #ifdef DEBUG_OLD
  1215.   VPrintf("ScanFDFile: scan Function\n", 0);
  1216. #endif
  1217.       STRPTR oldptr;
  1218.       struct AmiPragma ap;
  1219.  
  1220.       memset(&ap, 0, sizeof(struct AmiPragma));
  1221.       actcom = 0;
  1222.  
  1223.       oldptr = in.pos = SkipBlanks(in.pos);
  1224.       in.pos = SkipName(oldptr);
  1225.       if(!(len = in.pos-oldptr))
  1226.       {
  1227.     DoError(ERR_MISSING_FUNCTION_NAME, linenum);
  1228.     ++in.pos;
  1229.     continue;
  1230.       }
  1231.  
  1232.       ap.FuncName = oldptr;
  1233.  
  1234.       in.pos = SkipBlanks(in.pos);
  1235.       if(*in.pos != '(')
  1236.       {
  1237.     DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1238.     ++in.pos;
  1239.     continue;
  1240.       }
  1241.  
  1242.       *in.pos = '\0'; /* create c string of FunctionName */
  1243.  
  1244. #ifdef DEBUG_OLD
  1245.   VPrintf("ScanFDFile: found function %s\n", &ap.FuncName);
  1246. #endif
  1247.  
  1248.       do
  1249.       {
  1250.     oldptr = in.pos = SkipBlanks(in.pos+1);
  1251.  
  1252.     if(*in.pos == ')' && !ap.CallArgs)
  1253.       break;
  1254.  
  1255.     if(ap.CallArgs >= MAXREG-2)
  1256.     {
  1257.       DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
  1258.     }
  1259.  
  1260.     in.pos = SkipName(oldptr);
  1261.     if(*in.pos == '*')
  1262.       ++in.pos;
  1263.     if(!(len = in.pos-oldptr))
  1264.     {
  1265.       DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
  1266.       break;
  1267.     }
  1268.  
  1269.     ap.Args[ap.CallArgs++].ArgName = oldptr;
  1270.     oldptr = in.pos;
  1271.  
  1272.     in.pos = SkipBlanks(in.pos);
  1273.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  1274.     {
  1275.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1276.       break;
  1277.     }
  1278.     if(*in.pos != ')') /* create c string ending */
  1279.       *oldptr = '\0';
  1280.       }
  1281.       while(*in.pos != ')');
  1282.       if(*in.pos != ')')
  1283.       {
  1284.     while(*(in.pos++))
  1285.       ++in.pos;
  1286.     continue;
  1287.       }
  1288.       else
  1289.     *oldptr = '\0'; /* create c string ending for last argument */
  1290.  
  1291.       if(*(in.pos = SkipBlanks(in.pos+1)) != '(')
  1292.       {
  1293.     DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1294.     ++in.pos;
  1295.     continue;
  1296.       }
  1297.  
  1298.       do
  1299.       {
  1300.     ULONG i;
  1301.  
  1302.     oldptr = in.pos = SkipBlanks(in.pos + 1);
  1303.  
  1304.     if(*in.pos == ')' && !ap.NumArgs)
  1305.       break;
  1306.  
  1307.     in.pos = SkipName(oldptr);
  1308.     len = in.pos-oldptr;
  1309.  
  1310.     for(i = 0; i < MAXREG; ++i)
  1311.           if(!strnicmp(RegNames[i], oldptr, len))
  1312.             break;
  1313.  
  1314.     if(i == MAXREG)
  1315.     {
  1316.       DoError(ERR_EXPECTED_REGISTER_NAME, linenum);
  1317.       break;
  1318.     }
  1319.     else if(i == REG_A6)
  1320.       ap.Flags |= AMIPRAGFLAG_A6USE;
  1321.     else if(i == REG_A5)
  1322.       ap.Flags |= AMIPRAGFLAG_A5USE;
  1323.     else if(i == REG_A4)
  1324.       ap.Flags |= AMIPRAGFLAG_A4USE;
  1325.     else if(i == REG_D7)
  1326.       ap.Flags |= AMIPRAGFLAG_D7USE;
  1327.     else if(i == REG_A7)
  1328.     {
  1329.       DoError(ERR_A7_NOT_ALLOWED, linenum);
  1330.       break;
  1331.     }
  1332.     else if(i >= REG_FP0)
  1333.       ap.Flags |= AMIPRAGFLAG_FLOATARG;
  1334.  
  1335.     ap.Args[ap.NumArgs].ArgReg = i;
  1336.  
  1337.     if(ap.CallArgs < ap.NumArgs)    /* get name when no given */
  1338.       ap.Args[ap.NumArgs].ArgName = RegNames[i];
  1339.  
  1340.     for(i = 0; i < ap.NumArgs; i++)
  1341.     {
  1342.       if(ap.Args[ap.NumArgs].ArgReg == ap.Args[i].ArgReg)
  1343.       {
  1344.         DoError(ERR_REGISTER_USED_TWICE, linenum);
  1345.         break;
  1346.       }
  1347.     }
  1348.     if(i < ap.NumArgs)
  1349.       break;
  1350.  
  1351.     ++ap.NumArgs;
  1352.  
  1353.     in.pos = SkipBlanks(in.pos);
  1354.     if(*in.pos != ',' && *in.pos != '/' && *in.pos != ')')
  1355.     {
  1356.       DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1357.       break;
  1358.     }
  1359.       }
  1360.       while(*in.pos != ')');
  1361.  
  1362.       ap.Bias = bias;
  1363.       ap.Line = linenum;
  1364.       bias += BIAS_OFFSET;
  1365.  
  1366.       if(*in.pos != ')')
  1367.       {
  1368.     while(*(in.pos++))
  1369.       ++in.pos;
  1370.     continue;
  1371.       }
  1372.       else
  1373.     ++in.pos;
  1374.  
  1375.       if(Flags & FLAG_STORMFD)
  1376.       {
  1377.     if(!strcmp(ap.Args[ap.CallArgs-1].ArgName, "tags"))
  1378.     {
  1379.       ap.TagName = ap.FuncName;
  1380.       ap.FuncName = 0;
  1381.       ++tagfuncs;
  1382. #ifdef DEBUG_OLD
  1383.   VPrintf("ScanFDFile: StormFD mode, tag func: %s\n", &ap.TagName);
  1384. #endif
  1385.     }
  1386. #ifdef DEBUG_OLD
  1387.   else
  1388.   {
  1389.     STRPTR a[2];
  1390.     a[0] = ap.FuncName;
  1391.     a[1] = ap.Args[ap.CallArgs-1].ArgName;
  1392.     VPrintf("ScanFDFile: StormFD mode, normal func: %s(..., %s)\n", &a);
  1393.   }
  1394. #endif
  1395.       }
  1396.       else if((_public || (Flags & FLAG_PRIVATE)) && !MakeTagFunction(&ap))
  1397.     return 0;
  1398.       else    /* check the alias names */
  1399.       {
  1400.         ULONG i = 0;
  1401.  
  1402.         while(Pragma_AliasNames[i].FunctionName &&
  1403.         strcmp(ap.FuncName, Pragma_AliasNames[i].FunctionName))
  1404.           ++i;
  1405.  
  1406.         if(Pragma_AliasNames[i].FunctionName)
  1407.           ap.AliasName = &Pragma_AliasNames[i];
  1408.       }
  1409.  
  1410.       if(ap.CallArgs != ap.NumArgs)
  1411.     ap.Flags |= AMIPRAGFLAG_ARGCOUNT;
  1412.  
  1413.       if(bias == -1)
  1414.       {
  1415.     DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
  1416.     bias = 30;
  1417.       }
  1418.  
  1419.       if(_public)
  1420.         ap.Flags |= AMIPRAGFLAG_PUBLIC;
  1421.  
  1422.       if((Flags & FLAG_NOFPU) && (ap.Flags & AMIPRAGFLAG_FLOATARG))
  1423.     DoError(ERR_FLOATARG_NOT_ALLOWED, linenum);
  1424.       else if((ap.Flags & AMIPRAGFLAG_FLOATARG) || !(Flags & FLAG_FPUONLY))
  1425.       { /* skip all without FPU when FPUONLY */
  1426.     struct AmiPragma *d;
  1427.     if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  1428.       return 0;
  1429.     CopyMem(&ap, d, sizeof(struct AmiPragma));
  1430.     AddItem(&AmiPragma, (struct ShortList *) d);
  1431.     if(!SpecialFuncs())
  1432.       return 0;
  1433.       }
  1434.     }
  1435.  
  1436.     in.pos = SkipBlanks(in.pos);
  1437.     if(*in.pos)
  1438.       DoError(ERR_EXTRA_CHARACTERS, linenum);
  1439.     ++in.pos; /* skip '\0' */
  1440.   }
  1441.  
  1442.   if(CTRL_C)
  1443.   {
  1444.     DoError(ERR_USER_ABORT, 0);
  1445.     return 0;
  1446.   }
  1447.  
  1448.   if(bias)
  1449.     DoError(ERR_MISSING_END, 0);
  1450.  
  1451.   return 1;
  1452. }
  1453.  
  1454. LONG ScanTypes(STRPTR ptr, ULONG size)
  1455. {
  1456.   struct CPP_ExternNames *a = 0, *b = 0;
  1457.   STRPTR endptr = ptr+size;
  1458.   LONG line;
  1459.  
  1460.   for(line = 1; ptr < endptr; ++line)
  1461.   {
  1462.     struct CPP_ExternNames *n;
  1463.  
  1464.     if(*ptr == '*') /* skip comments */
  1465.     {
  1466.       while(ptr < endptr && *(ptr++) != '\n')
  1467.         ;
  1468.     }
  1469.     else if((n = (struct CPP_ExternNames *)
  1470.       AllocListMem(sizeof(struct CPP_ExternNames))))
  1471.     {
  1472.       STRPTR wptr;
  1473.  
  1474.       n->Type = ptr; /* store start */
  1475.  
  1476.       wptr = ptr;
  1477.       while(ptr < endptr && *ptr != ':' && *ptr != '\n')
  1478.       {
  1479.         if(*ptr == '\t' || *ptr == ' ')
  1480.         {
  1481.           *(wptr++) = ' ';
  1482.           ptr = SkipBlanks(ptr);
  1483.         }
  1484.         else
  1485.           *(wptr++) = *(ptr++);
  1486.       }
  1487.       if(*(ptr++) != ':')
  1488.         return line;
  1489.       if(*(wptr-1) == ' ')
  1490.         --wptr;
  1491.       *wptr = 0;
  1492.       
  1493.       if(!GetCPPType(&n->NameType, (ptr = SkipBlanks(ptr))))
  1494.         return line;
  1495. #ifdef DEBUG_OLD
  1496.   Printf("'%20s', slen %2ld, typelen %2ld, pntd %ld, type %lc, sn '%.3s'\n",
  1497.   n->Type, n->NameType.StructureLength, n->NameType.FullLength,
  1498.   n->NameType.PointerDepth, n->NameType.Type ? n->NameType.Type : 's',
  1499.   n->NameType.StructureName ? n->NameType.StructureName : "<e>");
  1500. #endif
  1501.       ptr = SkipBlanks(n->NameType.TypeStart+n->NameType.FullLength);
  1502.       if(*(ptr++) != '\n')
  1503.       {
  1504. #ifdef DEBUG_OLD
  1505.   Printf("%.30s\n", ptr);
  1506. #endif
  1507.         return line;
  1508.       }
  1509.  
  1510.       if(!a)
  1511.         b = n;
  1512.       else
  1513.         a->Next = n;
  1514.       a = n;
  1515.     }
  1516.     else
  1517.       return -1;
  1518.   }
  1519.   extnames = b; /* now store the list */
  1520.   return 0;
  1521. }
  1522.  
  1523. void FindHeader(void)
  1524. {
  1525.   STRPTR str = HEADER;
  1526.   ULONG mode = 0;
  1527.  
  1528.   do
  1529.   {
  1530.     if(!mode)
  1531.       HEADER = str;
  1532.  
  1533.     if(*str == '/')
  1534.     {
  1535.       ++str;
  1536.       if(*str == '*')
  1537.       {
  1538.     mode = 2; break;
  1539.       }
  1540.       else if(*str == '/')
  1541.     mode = 1;
  1542.     }
  1543.     else if(*str == '*' || *str == ';')
  1544.       mode = 1;
  1545.     else if(*str == '{'/*}*/)
  1546.     {
  1547.       mode = 3; break;
  1548.     }
  1549.     else if(*str == '('/*)*/ && *(++str) == '*')
  1550.     {
  1551.       mode = 4; break;
  1552.     }
  1553.     else if(mode)
  1554.       break;
  1555.     while(*str && *(str++) != '\n')
  1556.       ;
  1557.   } while(*str);
  1558.  
  1559.   if(mode == 2)
  1560.   {
  1561.     while(*str && (*(str-1) != '*' || *str != '/'))
  1562.       ++str;
  1563.     while(*str && *(str++) != '\n')
  1564.       ;
  1565.   }
  1566.   else if(mode == 3)
  1567.   {
  1568.     while(*str && *str != /*{*/'}')
  1569.       ++str;
  1570.     while(*str && *(str++) != '\n')
  1571.       ;
  1572.   }
  1573.   else if(mode == 4)
  1574.   {
  1575.     while(*str && (*(str-1) != '*' || *str != /*(*/')'))
  1576.       ++str;
  1577.     while(*str && *(str++) != '\n')
  1578.       ;
  1579.   }
  1580.  
  1581.   if(mode)
  1582.     headersize = str-HEADER;
  1583.   else
  1584.   {
  1585.     HEADER = 0; headersize = 0;
  1586.   }
  1587. }
  1588.  
  1589. /* returns decrement data in bits 0-15 and increment data in bits 16-31 */
  1590. ULONG GetRegisterData(struct AmiPragma *ap)
  1591. {
  1592. /* usage of result:
  1593.     48E7 <lower word>    MOVEM.L <registers>,-(A7) ; D0 is bit 15
  1594.     4CDF <upper word>    MOVEM.L (A7)+,<registers> ; D0 is bit 0
  1595. */
  1596.   register ULONG i, data = 0, reg;
  1597.  
  1598.   for(i = 0; i < ap->NumArgs; ++i)
  1599.   {
  1600.     if((reg = ap->Args[i].ArgReg) <= REG_FP0)
  1601.     {
  1602.       if(reg >= 10 || (reg >= 2 &&  reg <= 7)) /* A2-A7 and D2-D7 */
  1603.         data |= (1 << (reg + 16)) + (1 << (15 - reg));
  1604.     }
  1605.   }
  1606.   if(data)    /* set A6 only when other register used */
  1607.     data |= 0x40000002;
  1608.   return data;
  1609. }
  1610.  
  1611. UWORD GetFRegisterData(struct AmiPragma *ap)
  1612. {
  1613. /* usage of result:
  1614.     F227 <upper byte>    FMOVEM.X <registers>,-(A7) ; FP0 is bit 0
  1615.     F21F <lower byte>    FMOVEM.X (A7)+,<registers> ; FP0 is bit 7
  1616. */
  1617.   register ULONG i, reg;
  1618.   register UWORD data = 0;
  1619.  
  1620.   for(i = 0; i < ap->NumArgs; ++i)
  1621.   {
  1622.     if((reg = ap->Args[i].ArgReg) >= REG_FP2)
  1623.     {
  1624.       reg -= REG_FP0;
  1625.       data |= (1 << (reg + 8)) + (1 << (7 - reg));
  1626.     }
  1627.   }
  1628.   return data;
  1629. }
  1630.  
  1631. ASM(static void) SAVEDS xdefputfunc(REG(d0, UBYTE data), REG(a3, STRPTR *a))
  1632. {
  1633. #ifdef __MAXON__
  1634.   GetBaseReg();
  1635. #endif
  1636.   *((*a)++) = data;
  1637. }
  1638.  
  1639. ULONG OutputXDEF(STRPTR format, ...)
  1640. {
  1641.   UBYTE b[150];
  1642.   STRPTR c = b + 4;
  1643.   UWORD i;
  1644.  
  1645.   memset(b, 0, 150);
  1646.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  1647.   (void(*)()) xdefputfunc, &c);
  1648.   /* c now holds pointer to end */
  1649.   i = (c-(b+4)+2)>>2;
  1650.   *((ULONG *) b) = 0x01000000 + i;
  1651.  
  1652.   return DoOutputDirect(b, (i+2)<<2);
  1653. }
  1654.  
  1655. UWORD *AsmStackCopy(UWORD *data, struct AmiPragma *ap, ULONG flags,
  1656. ULONG ofs)
  1657. {
  1658.   ULONG j, k;
  1659.  
  1660.   if(Flags & FLAG_PASCAL)
  1661.   {
  1662.     k = ap->NumArgs;
  1663.  
  1664.     while(k)
  1665.     {
  1666.       if(ap->Args[k-1].ArgReg >= REG_FP0)
  1667.       {
  1668.         struct ClibData *cd; 
  1669.  
  1670.     cd = GetClibFunc(ap->FuncName, ap, flags);
  1671.         *(data++) = 0xF22F;        /* FMOVE.? offs(A7),FPx */
  1672.  
  1673.         if(cd && IsCPPType(&cd->Args[k-1], CPP_TYPE_DOUBLE))
  1674.         {
  1675.           *(data++) = 0x5400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
  1676.           *(data++) = ofs<<2; /* one double needs two longs */
  1677.           ofs += 2;
  1678.         }
  1679.         else
  1680.         {
  1681.           if(!cd || !IsCPPType(&cd->Args[k-1], CPP_TYPE_FLOAT))
  1682.             DoError(ERR_LONG_DOUBLE, ap->Line);
  1683.           *(data++) = 0x4400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
  1684.           *(data++) = (ofs++) << 2;
  1685.         }
  1686.       }
  1687.       else if((k >= 2) && (ap->Args[k-1].ArgReg < ap->Args[k-2].ArgReg)
  1688.       && ap->Args[k-2].ArgReg < REG_FP0)
  1689.       {
  1690.         *(data++) = 0x4CEF;        /* MOVEM.L offs(A7),xxx */
  1691.         *(data++) = 0;
  1692.         *(data++) = ofs << 2;        /* store start offset */
  1693.         do
  1694.         {
  1695.           j = ap->Args[--k].ArgReg;
  1696.  
  1697.       ++ofs;
  1698.           *(data-2) |= 1 << j;
  1699.         } while(k && j < ap->Args[k-1].ArgReg &&
  1700.           ap->Args[k-1].ArgReg < REG_FP0);
  1701.       }
  1702.       else
  1703.       {
  1704.         *data = 0x202F;            /* MOVE.L offs(A7),xxx */
  1705.  
  1706.         if((j = ap->Args[--k].ArgReg) > 7)
  1707.         {
  1708.           *data |= (1<<6); j -= 8;    /* set MOVEA bit */
  1709.         }
  1710.         *(data++) |= j << 9;        /* set destination register */
  1711.         *(data++) = (ofs++) << 2;
  1712.       }
  1713.     }
  1714.   }
  1715.   else
  1716.   {
  1717.     ULONG i = 0;
  1718.  
  1719.     k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
  1720.  
  1721.     while(i < k)
  1722.     {
  1723.       if(ap->Args[i].ArgReg >= REG_FP0)
  1724.       {
  1725.         struct ClibData *cd; 
  1726.  
  1727.     cd = GetClibFunc(ap->FuncName, ap, flags);
  1728.         *(data++) = 0xF22F;        /* FMOVE.? offs(A7),FPx */
  1729.  
  1730.         if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
  1731.         {
  1732.           *(data++) = 0x5400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
  1733.           *(data++) = ofs<<2; /* one double needs two longs */
  1734.           ofs += 2;
  1735.         }
  1736.         else
  1737.         {
  1738.           if(!cd || !IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
  1739.             DoError(ERR_LONG_DOUBLE, ap->Line);
  1740.           *(data++) = 0x4400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
  1741.           *(data++) = (ofs++) << 2;
  1742.         }
  1743.       }
  1744.       else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg)
  1745.       && ap->Args[i+1].ArgReg < REG_FP0)
  1746.       {
  1747.         *(data++) = 0x4CEF;        /* MOVEM.L offs(A7),xxx */
  1748.         *(data++) = 0;            /* Store MOVEM.L data later */
  1749.         *(data++) = ofs << 2;        /* store start offset */
  1750.         do
  1751.         {
  1752.           j = ap->Args[i++].ArgReg;
  1753.  
  1754.       ++ofs;
  1755.           *(data-2) |= 1 << j;
  1756.         } while(i < k && j < ap->Args[i].ArgReg &&
  1757.         ap->Args[i].ArgReg < REG_FP0);
  1758.       }
  1759.       else
  1760.       {
  1761.         *data = 0x202F;            /* MOVE.L offs(A7),xxx */
  1762.  
  1763.         if((j = ap->Args[i++].ArgReg) > 7)
  1764.         {
  1765.           *data |= (1<<6); j -= 8;    /* set MOVEA bit */
  1766.         }
  1767.         *(data++) |= j << 9;        /* set destination register */
  1768.         *(data++) = (ofs++) << 2;
  1769.       }
  1770.     }
  1771.  
  1772.     if(i < ap->NumArgs)
  1773.     {
  1774.       if((j = ap->Args[i].ArgReg) > 7)
  1775.       {
  1776.         *(data++) = 0x41EF | ((j-8) << 9);    /* LEA xxx(A7),Ax */
  1777.         *(data++) = ofs << 2;
  1778.       }
  1779.       else
  1780.       {
  1781.         *(data++) = 0x200F | (j << 9);        /* MOVE.L A7,Dx */
  1782.         if(ofs == 2)
  1783.           *(data++) = 0x5080 | j;         /* ADDQ.L #8,Dx */
  1784.         else
  1785.         {
  1786.       *(data++) = 0xD0BC | (j<<9);        /* ADD.L #x,Dx */
  1787.       *(data++) = 0;
  1788.       *(data++) = ofs << 2;
  1789.         }
  1790.       }
  1791.     }
  1792.   }
  1793.  
  1794.   return data;
  1795. }
  1796. /* ------------------------------------------------------------------ */
  1797.  
  1798. void DoError(UBYTE errnum, ULONG line, ...)
  1799. {
  1800.   if(Flags & FLAG_DIDERROR)
  1801.     return;
  1802.  
  1803.   if(!Errors[errnum].Type)
  1804.     Flags |= FLAG_DIDERROR;
  1805.  
  1806.   Printf((line ? "%s %ld in line %ld%s: " : "%s %ld : "), (ULONG)
  1807.   (Errors[errnum].Type ? "Warning" : "Error"), errnum, line,
  1808.   errnum == ERR_UNKNOWN_VARIABLE_TYPE ? " of clib file" : "");
  1809.   VPrintf(Errors[errnum].Error, (((STRPTR) &line) + sizeof(ULONG)));
  1810.   PutStr("\n");
  1811.   if(line && Errors[errnum].Skip)
  1812.   {
  1813.     while(*in.pos)
  1814.       ++in.pos;
  1815.   }
  1816. }
  1817.  
  1818. ULONG Out(ULONG size)
  1819. {
  1820.   ULONG i = out.pos-out.buf;
  1821.  
  1822.   if(i && out.size - i <= size)
  1823.   {
  1824.     if(Write(out.file, out.buf, i) != i)
  1825.     {
  1826.       Output_Error = 0;
  1827.       return 0;
  1828.     }
  1829.     out.pos = out.buf;
  1830.   }
  1831.   return out.size;
  1832. }
  1833.  
  1834. ASM(static void) SAVEDS putfunc(REG(d0, UBYTE data), REG(a3, LONG *a))
  1835. {
  1836. #ifdef __MAXON__
  1837.   GetBaseReg();
  1838. #endif
  1839.  
  1840.   if(data)
  1841.   {
  1842.     if(!*a)
  1843.       *a = Out(1);
  1844.     if((*a)-- > 0)
  1845.       *(out.pos++) = data;
  1846.   }
  1847. }
  1848.  
  1849. ULONG DoOutput(STRPTR format, ...)
  1850. {
  1851.   LONG a = out.buf+out.size-out.pos;
  1852.  
  1853.   if(!Output_Error)
  1854.     return 0;
  1855.  
  1856.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  1857.   (void(*)()) putfunc, &a);
  1858.  
  1859.   if(a < 0)
  1860.     return 0;
  1861.   return 1;
  1862. }
  1863.  
  1864. ULONG DoOutputDirect(APTR data, ULONG size)
  1865. {
  1866.   if(!Output_Error || !Out(size))
  1867.     return 0;
  1868.   CopyMem(data, out.pos, size);
  1869.   out.pos += size;
  1870.   return 1;
  1871. }
  1872.  
  1873. /* ------------------------------------------------------------------ */
  1874.  
  1875. struct ShortList *NewItem(struct ShortListRoot *list)
  1876. {
  1877.   struct ShortList *item;
  1878.   if(!list || !list->Size)
  1879.     return 0;
  1880.   if(!(item = (struct ShortList *) AllocListMem(list->Size)))
  1881.     return 0;
  1882.   return item;
  1883. }
  1884.  
  1885. struct ShortList *RemoveItem(struct ShortListRoot *list,
  1886. struct ShortList *item)
  1887. {
  1888.   struct ShortList *n = list->First;
  1889.  
  1890.   if(n == item)
  1891.     list->First = item->Next;
  1892.   else
  1893.   {
  1894.     while(n && n->Next != item)
  1895.       n = n->Next;
  1896.     if(!n)
  1897.       return 0;
  1898.     if(!(n->Next = item->Next))
  1899.       list->Last = n;
  1900.   }
  1901.   item->Next = 0;
  1902.   return item;
  1903. }
  1904.  
  1905. void AddItem(struct ShortListRoot *list, struct ShortList *item)
  1906. {
  1907.   if(!list->First)
  1908.     list->First = list->Last = item;
  1909.   else
  1910.   {
  1911.     list->Last->Next = item;
  1912.     list->Last = item;
  1913.   }
  1914. }
  1915.  
  1916. /* ------------------------------------------------------------------ */
  1917.  
  1918. ULONG FuncAMICALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
  1919. {
  1920.   ULONG i;
  1921.  
  1922.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  1923.   {
  1924.     if(!(ap->Flags & AMIPRAGFLAG_DIDWARN))
  1925.     {
  1926.       DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  1927.       ap->Flags |= AMIPRAGFLAG_DIDWARN;
  1928.     }
  1929.     return 1;
  1930.   }
  1931.  
  1932.   Flags |= FLAG_DONE; /* We did something */
  1933.  
  1934.   DoOutput("#pragma %s(%s,0x%03lx,%s("/*))*/, flags & FUNCFLAG_TAG ?
  1935.   "tagcall" : "amicall", BaseName, ap->Bias, name);
  1936.  
  1937.   for(i = 0; i < ap->NumArgs; ++i)
  1938.   {
  1939.     DoOutput(RegNames[ap->Args[i].ArgReg]);
  1940.     if(i+1 < ap->NumArgs)
  1941.       DoOutput(",");
  1942.   }
  1943.  
  1944.   return DoOutput(/*((*/"))\n");
  1945. }
  1946.  
  1947. ULONG FuncLIBCALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
  1948. {
  1949.   LONG i;
  1950.  
  1951.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  1952.   {
  1953.     if(!(ap->Flags & AMIPRAGFLAG_DIDWARN))
  1954.     {
  1955.       DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  1956.       ap->Flags |= AMIPRAGFLAG_DIDWARN;
  1957.     }
  1958.     return 1;
  1959.   }
  1960.  
  1961.   Flags |= FLAG_DONE; /* We did something */
  1962.  
  1963.   if(ap->Flags & AMIPRAGFLAG_FLOATARG)
  1964.   {
  1965.     DoOutput("#pragma flibcall %s %-20s %03lx ", BaseName, name, ap->Bias);
  1966.     for(i = ap->NumArgs-1; i >= 0; --i)
  1967.       DoOutput("%02lx", ap->Args[i].ArgReg);
  1968.  
  1969.     return DoOutput("00%02lx\n", ap->NumArgs);
  1970.   }
  1971.  
  1972.   if((Flags & FLAG_SYSCALL) && !strcmp(BaseName,"SysBase") &&
  1973.   (flags & FUNCFLAG_NORMAL))
  1974.     DoOutput("#pragma  syscall %-20s %03lx ", name, ap->Bias);
  1975.   else
  1976.     DoOutput("#pragma  %s %s %-20s %03lx ", (flags & FUNCFLAG_TAG) ?
  1977.     "tagcall" : "libcall", BaseName, name, ap->Bias);
  1978.  
  1979.   for(i = ap->NumArgs-1; i >= 0; --i)
  1980.     DoOutput("%lx", ap->Args[i].ArgReg);
  1981.  
  1982.   return DoOutput("0%lx\n", ap->NumArgs);
  1983. }
  1984.  
  1985. ULONG FuncAsmText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  1986. {
  1987.   LONG i;
  1988.   ULONG registers;
  1989.   UWORD fregs;
  1990.   ULONG offset = 1;
  1991.   struct ClibData *cd;
  1992.  
  1993.   Flags |= FLAG_DONE; /* We did something */
  1994.  
  1995.   if(Flags & FLAG_ASMSECTION)
  1996.   {
  1997.     DoOutput("\n\tSECTION\t\"%s\",CODE\n\tXREF\t_%s\n", name, BaseName);
  1998.   }
  1999.  
  2000.   DoOutput("\n\tXDEF\t_%s\n_%s:\n",name, name);
  2001.   if(!(Flags & FLAG_PASCAL))
  2002.   {
  2003.     DoOutput("\tXDEF\t%s\n%s:\n",name, name);
  2004.     if(clibdata)
  2005.     {
  2006.       if(!ap->NumArgs)
  2007.         DoOutput("\tXDEF\t%s_\n%s_:\n",name, name);
  2008.       else if((cd = GetClibFunc(name, ap, flags)))
  2009.       {
  2010.         UBYTE txt[300];
  2011.         ULONG ret = 0;
  2012.  
  2013.         do
  2014.         {
  2015.       if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
  2016.         DoOutput("\tXDEF\t%s__%s\n%s__%s:\n", name, txt, name, txt);
  2017.         } while(ret == 0xFFFFFFFF);
  2018.       }
  2019.     }
  2020.   }
  2021.  
  2022.   if((registers = GetRegisterData(ap) >> 16))
  2023.   {
  2024.     UWORD l = registers;
  2025.  
  2026.     DoOutput("\tMOVEM.L\t");
  2027.  
  2028.     for(i = 0; i <= 15; ++i)
  2029.     {
  2030.       if(l & (1 << i))
  2031.       {
  2032.     ++offset;
  2033.     l ^= 1 << i;
  2034.     DoOutput(RegNamesUpper[i]);
  2035.     if(l)
  2036.       DoOutput("/");
  2037.       }
  2038.     }
  2039.     DoOutput(",-(A7)\n");
  2040.   }
  2041.   else
  2042.   {
  2043.     DoOutput("\tMOVE.L\tA6,-(A7)\n"); ++offset;
  2044.   }
  2045.  
  2046.   if((fregs = GetFRegisterData(ap) >> 8))
  2047.   {
  2048.     UBYTE l = fregs;
  2049.  
  2050.     DoOutput("\tFMOVEM.X\t");
  2051.  
  2052.     for(i = 0; i <= 7; ++i)
  2053.     {
  2054.       if(l & (1 << i))
  2055.       {
  2056.     offset += 3;
  2057.     l ^= 1 << i;
  2058.     DoOutput(RegNamesUpper[REG_FP0 + i]);
  2059.     if(l)
  2060.       DoOutput("/");
  2061.       }
  2062.     }
  2063.     DoOutput(",-(A7)\n");
  2064.   }
  2065.  
  2066.   if(Flags & FLAG_SMALLDATA)
  2067.     DoOutput("\tMOVEA.L\t_%s(A4),A6\n", BaseName);
  2068.   else
  2069.     DoOutput("\tMOVEA.L\t_%s,A6\n", BaseName);
  2070.  
  2071.   if(!(Flags & FLAG_PASCAL))
  2072.   {
  2073.     ULONG k;
  2074.  
  2075.     k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
  2076.  
  2077.     for(i = 0; i < k;)
  2078.     {
  2079.       if(ap->Args[i].ArgReg >= REG_FP0)
  2080.       {
  2081.         ULONG t;
  2082.     struct ClibData *cd;
  2083.  
  2084.     cd = GetClibFunc(name, ap, flags);
  2085.     if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
  2086.       t = CPP_TYPE_DOUBLE;
  2087.     else if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
  2088.       t = CPP_TYPE_FLOAT;
  2089.         else
  2090.         {
  2091.           DoError(ERR_LONG_DOUBLE, ap->Line);
  2092.       t = CPP_TYPE_FLOAT;
  2093.     }
  2094.  
  2095.     DoOutput("\tFMOVE.%lc\t%02ld(A7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S',
  2096.     offset<<2, RegNamesUpper[ap->Args[i++].ArgReg]);
  2097.     if(t == CPP_TYPE_DOUBLE)
  2098.       ++offset;
  2099.         ++offset;
  2100.       }
  2101.       else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg) &&
  2102.       ap->Args[i+1].ArgReg < REG_FP0)
  2103.       {
  2104.         DoOutput("\tMOVEM.L\t%02ld(A7),%s", (offset++)<<2,
  2105.         RegNamesUpper[ap->Args[i++].ArgReg]);
  2106.  
  2107.         do
  2108.         {
  2109.       DoOutput("/%s", RegNamesUpper[ap->Args[i++].ArgReg]);
  2110.       ++offset;
  2111.         } while((i < k) && (ap->Args[i-1].ArgReg < ap->Args[i].ArgReg) &&
  2112.         ap->Args[i].ArgReg < REG_FP0);
  2113.     DoOutput("\n");
  2114.       }
  2115.       else
  2116.       {
  2117.         DoOutput("\tMOVE%s.L\t%02ld(A7),%s\n",
  2118.         ap->Args[i].ArgReg >= REG_A0 ? "A" : "", (offset++)<<2,
  2119.         RegNamesUpper[ap->Args[i].ArgReg]);
  2120.         ++i;
  2121.       }
  2122.     }
  2123.  
  2124.     if(i < ap->NumArgs)
  2125.     {
  2126.       if(ap->Args[i].ArgReg > 7)
  2127.     DoOutput("\tLEA\t%02ld(A7),%s\n", offset<<2,
  2128.     RegNamesUpper[ap->Args[i].ArgReg]);
  2129.       else
  2130.     DoOutput("\tMOVE.L\tA7,%s\n\tADD%s.L\t#%02ld,%s\n",
  2131.     RegNamesUpper[ap->Args[i].ArgReg], (offset <= 2 ? "Q" : ""),
  2132.     offset<<2, RegNamesUpper[ap->Args[i].ArgReg]);
  2133.     }
  2134.   }
  2135.   else
  2136.   {
  2137.     i = ap->NumArgs;
  2138.  
  2139.     while(i)
  2140.     {
  2141.       if(ap->Args[i-1].ArgReg >= REG_FP0)
  2142.       {
  2143.         ULONG t;
  2144.     struct ClibData *cd;
  2145.  
  2146.     cd = GetClibFunc(name, ap, flags);
  2147.  
  2148.     if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_DOUBLE))
  2149.       t = CPP_TYPE_DOUBLE;
  2150.     else if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_FLOAT))
  2151.       t = CPP_TYPE_FLOAT;
  2152.         else
  2153.         {
  2154.           DoError(ERR_LONG_DOUBLE, ap->Line);
  2155.       t = CPP_TYPE_FLOAT;
  2156.     }
  2157.  
  2158.     DoOutput("\tFMOVE.%lc\t%02ld(A7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S',
  2159.     offset<<2, RegNamesUpper[ap->Args[--i].ArgReg]);
  2160.     if(t == CPP_TYPE_DOUBLE)
  2161.       ++offset;
  2162.         ++offset;
  2163.       }
  2164.       else if((i >= 2) && (ap->Args[i-1].ArgReg < ap->Args[i-2].ArgReg) &&
  2165.       ap->Args[i-2].ArgReg < REG_FP0)
  2166.       {
  2167.         DoOutput("\tMOVEM.L\t%02ld(A7),%s", (offset++)<<2,
  2168.         RegNamesUpper[ap->Args[--i].ArgReg]);
  2169.  
  2170.         do
  2171.         {
  2172.       DoOutput("/%s", RegNamesUpper[ap->Args[--i].ArgReg]);
  2173.       ++offset;
  2174.         } while(i && (ap->Args[i].ArgReg < ap->Args[i-1].ArgReg) &&
  2175.         ap->Args[i-1].ArgReg < REG_FP0);
  2176.     DoOutput("\n");
  2177.       }
  2178.       else
  2179.       {
  2180.         --i;
  2181.         DoOutput("\tMOVE%s.L\t%02ld(A7),%s\n",
  2182.         ap->Args[i].ArgReg >= REG_A0 ? "A" : "", (offset++)<<2,
  2183.         RegNamesUpper[ap->Args[i].ArgReg]);
  2184.       }
  2185.     }
  2186.   }
  2187.  
  2188.   DoOutput("\tJSR\t-%03ld(A6)\n",ap->Bias);
  2189.  
  2190.   if(fregs)
  2191.   {
  2192.     DoOutput("\tFMOVEM.X\t(A7)+,");
  2193.  
  2194.     for(i = 0; i <= 7; ++i)
  2195.     {
  2196.       if(fregs & (1 << i))
  2197.       {
  2198.     fregs ^= 1 << i;
  2199.     DoOutput(RegNamesUpper[REG_FP0 + i]);
  2200.     if(fregs)
  2201.       DoOutput("/");
  2202.       }
  2203.     }
  2204.     DoOutput("\n");
  2205.   }
  2206.  
  2207.   if(registers)
  2208.   {
  2209.     DoOutput("\tMOVEM.L\t(A7)+,");
  2210.  
  2211.     for(i = 0; i <= 15; ++i)
  2212.     {
  2213.       if(registers & (1 << i))
  2214.       {
  2215.     registers ^= 1 << i;
  2216.     DoOutput(RegNamesUpper[i]);
  2217.     if(registers)
  2218.       DoOutput("/");
  2219.       }
  2220.     }
  2221.     DoOutput("\n");
  2222.   }
  2223.   else
  2224.     DoOutput("\tMOVEA.L\t(A7)+,A6\n");
  2225.  
  2226.   return DoOutput("\tRTS\n");
  2227. }
  2228.  
  2229. ULONG FuncAsmCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2230. {
  2231.   ULONG registers, a[5], offset = 1, pos = 4, baseref;
  2232.   LONG i = strlen(ShortBaseNameUpper);
  2233.   UWORD data[100]; /* 200 byte data field */
  2234.   UWORD fregs;
  2235.  
  2236.   Flags |= FLAG_DONE; /* We did something */
  2237.  
  2238.   registers = GetRegisterData(ap);
  2239.  
  2240.   fregs = GetFRegisterData(ap);
  2241.  
  2242.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  2243.   a[3] = (i + 6 + 3)>>2;
  2244.  
  2245.   DoOutputDirect(a, 16);
  2246.   DoOutputDirect(ShortBaseNameUpper, i);
  2247.   DoOutputDirect("_STUBS\0\0\0", (a[3]<<2)-i);
  2248.  
  2249.   data[0] = 0;
  2250.   data[1] = HUNK_CODE;
  2251.   data[2] = 0;
  2252.   /* data[3] is size */
  2253.  
  2254.   if(!registers)
  2255.   {
  2256.     data[pos++] = 0x2F0E;        /* MOVE.L A6,-(A7) */
  2257.     ++offset;                /* one long more on stack */
  2258.   }
  2259.   else
  2260.   {
  2261.     ULONG l;
  2262.     data[pos++] = 0x48E7;        /* MOVEM.L xxx,-(A7) */
  2263.     data[pos++] = registers;        /* storem MOVEM.L registers */
  2264.     for(l = (UWORD) registers; l; l >>= 1)
  2265.     {
  2266.       if(l & 1)
  2267.     ++offset;            /* get offset addition */
  2268.     }
  2269.   }
  2270.  
  2271.   if(fregs)
  2272.   {
  2273.     ULONG l;
  2274.     data[pos++] = 0xF227;        /* FMOVEM.X xxx,-(A7) */
  2275.     data[pos++] = 0xE000 + ((fregs>>8)&0xFF);
  2276.     for(l = (UBYTE) fregs; l; l >>= 1)
  2277.     {
  2278.       if(l & 1)
  2279.     offset+=3;            /* get offset addition */
  2280.     }
  2281.   }
  2282.  
  2283.   baseref = pos+1-4;        /* one word later (MOVE) - 2 header longs */
  2284.   if(Flags & FLAG_SMALLDATA)
  2285.   {
  2286.     data[pos++] = 0x2C6C;        /* MOVEA.L base(A4),A6 */
  2287.     data[pos++] = 0;            /* place for base reference */
  2288.   }
  2289.   else
  2290.   {
  2291.     data[pos++] = 0x2C79;        /* MOVEA.L base,A6 */
  2292.     data[pos++] = 0;            /* place for base reference */
  2293.     data[pos++] = 0;
  2294.   }
  2295.  
  2296.   pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
  2297.  
  2298.   /* here comes the base reference */
  2299.   data[pos++] = 0x4EAE;            /* JSR xxx(A6) */
  2300.   data[pos++] = -ap->Bias;        /* JSR offset */
  2301.  
  2302.   if(fregs)
  2303.   {
  2304.     data[pos++] = 0xF21F;        /* FMOVEM.X (A7)+,xxx */
  2305.     data[pos++] = 0xD000 + (fregs&0xFF);
  2306.   }
  2307.  
  2308.   if(registers)
  2309.   {
  2310.     data[pos++] = 0x4CDF;        /* MOVEM.L (A7)+,xxx */
  2311.     data[pos++] = (registers >> 16);    /* store MOVEM.L registers */
  2312.   }
  2313.   else
  2314.     data[pos++] = 0x2C5F;        /* MOVE.L (A7)+,A6 */
  2315.   data[pos++] = 0x4E75;            /* RTS */
  2316.  
  2317.   if(pos & 1)
  2318.     data[pos++] = 0;            /* round to long */
  2319.  
  2320.   data[3] = (pos-4)>>1;            /* store hunk len */
  2321.   DoOutputDirect(data, pos<<1);
  2322.  
  2323.   a[0] = HUNK_EXT;
  2324.   a[1] = ((Flags & FLAG_SMALLDATA ? EXT_REF16 : EXT_REF32) << 24) +
  2325.          ((strlen(BaseName) + 1 + 3)>>2);
  2326.   a[2] = ('_' << 24);
  2327.  
  2328.   DoOutputDirect(a, 9);
  2329.   DoOutputDirect(BaseName, (((UWORD) a[1])<<2)-1);
  2330.  
  2331.   a[0] = 1; a[1] = baseref << 1;
  2332.   DoOutputDirect(a, 8);
  2333.  
  2334.   /* here come the XDEF name references */
  2335.   OutputXDEF("_%s", name);        /* C name */
  2336.  
  2337.   if(!(Flags & FLAG_PASCAL))
  2338.   {
  2339.     struct ClibData *cd;
  2340.     OutputXDEF("%s", name);        /* ASM name */
  2341.  
  2342.     if(clibdata)
  2343.     {
  2344.       if(!ap->NumArgs)
  2345.         OutputXDEF("%s_", name);    /* C++ name no parameters */
  2346.       else if((cd = GetClibFunc(name, ap, flags)))
  2347.       {
  2348.         ULONG ret = 0;
  2349.  
  2350.         do                /* C++ name with parameters */
  2351.         {
  2352.       if((ret = CopyCPPType((STRPTR) data, ret, cd, ap->Args)))
  2353.         OutputXDEF("%s__%s", name, (STRPTR) data);
  2354.         }   while(ret == 0xFFFFFFFF);
  2355.       }
  2356.     }
  2357.   }
  2358.  
  2359.   a[0] = 0; a[1] = HUNK_END;
  2360.  
  2361.   return DoOutputDirect(a, 8);
  2362. }
  2363.  
  2364. /* Directly called by FuncInline also! */
  2365. ULONG FuncCSTUBS(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2366. {
  2367.   struct ClibData *f, *t;
  2368.   STRPTR ret = "return ";
  2369.   ULONG i;
  2370.  
  2371.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  2372.   {
  2373.     DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  2374.     return 1;
  2375.   }
  2376.  
  2377.   Flags |= FLAG_DONE; /* We did something */
  2378.  
  2379.   if(!(f = GetClibFunc(ap->FuncName, ap, 0)))
  2380.     return 1;
  2381.   t = GetClibFunc(name, ap, flags);
  2382.  
  2383.   if(IsCPPType(&f->ReturnType, CPP_TYPE_VOID))
  2384.     ret = 0;
  2385.  
  2386.   if(!OutClibType(&f->ReturnType, name) || !DoOutput("("/*)*/))
  2387.     return 0;
  2388.   for(i = 0; i < ap->NumArgs-1; i++)
  2389.   {
  2390.     if(!OutClibType(&f->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  2391.       return 0;
  2392.   }
  2393.   if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
  2394.   {
  2395.     if(!OutClibType(&t->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  2396.       return 0;
  2397.   }
  2398.   else if(ap->NumArgs == 1 && !DoOutput("ULONG tag, "))
  2399.     return 0;
  2400.  
  2401.   if(!DoOutput(/*(*/"...)\n{\n  %s%s("/*)*/, ret, ap->FuncName))
  2402.     return 0;
  2403.   for(i = 0; i < ap->NumArgs-1; i++)
  2404.   {
  2405.     if(!DoOutput("%s, ", ap->Args[i].ArgName))
  2406.       return 0;
  2407.   }
  2408.   if(!DoOutput("("/*)*/) || !OutClibType(&f->Args[ap->NumArgs-1],0))
  2409.     return 0;
  2410.  
  2411.   if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
  2412.   {
  2413.     if(!DoOutput(/*((*/") &%s);\n}\n\n", ap->Args[ap->NumArgs-1].ArgName))
  2414.       return 0;
  2415.   }
  2416.   else if(ap->NumArgs == 1)
  2417.   {
  2418.     if(!DoOutput(/*((*/") &tag);\n}\n\n"))
  2419.       return 0;
  2420.   }
  2421.   else if (!DoOutput(/*(*/") ((ULONG) &%s + sizeof("/*))*/,
  2422.   ap->Args[ap->NumArgs-2].ArgName) || !OutClibType(&f->Args[ap->NumArgs-2],0)
  2423.   || !DoOutput(/*(((*/")));\n}\n\n"))
  2424.     return 0;
  2425.   return 1;
  2426. }
  2427.  
  2428. ULONG FuncLVOXDEF(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2429. {
  2430.   Flags |= FLAG_DONE; /* We did something */
  2431.   return DoOutput("\t\tXDEF\t_LVO%s\n", name);
  2432. }
  2433.  
  2434. ULONG FuncLVO(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2435. {
  2436.   Flags |= FLAG_DONE; /* We did something */
  2437.   return DoOutput("\n_LVO%-24s\tEQU\t-%ld", name, ap->Bias);
  2438. }
  2439.  
  2440. ULONG FuncLocCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2441. {
  2442.   ULONG a[5];
  2443.   STRPTR str2 = Flags & FLAG_LOCALREG ? "rE" : "";
  2444.   LONG i = strlen(ShortBaseNameUpper);
  2445.   ULONG j;
  2446.   struct ClibData *cd;
  2447.  
  2448.   Flags |= FLAG_DONE; /* We did something */
  2449.  
  2450.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  2451.   a[3] = (i + 4 + 3)>>2;
  2452.  
  2453.   DoOutputDirect(a, 16);
  2454.   DoOutputDirect(ShortBaseNameUpper, i);
  2455.   DoOutputDirect("_LOC\0\0\0", (a[3]<<2)-i);
  2456.  
  2457.   if(Flags & FLAG_LOCALREG)
  2458.   {
  2459.     if((flags & FUNCFLAG_TAG))
  2460.     {
  2461.       j = ap->Args[ap->NumArgs-1].ArgReg;
  2462.       a[0] = HUNK_CODE; a[1] = 4;
  2463.       a[2] = 0x2F000000 + (j << 16);    /* MOVE <ea>,-(A7) */
  2464.  
  2465.       DoOutputDirect(a, 10);
  2466.  
  2467.       a[1] = 0x4EAE0000 + (UWORD) (- ap->Bias); /* JSR instruction */
  2468.       a[2] = 0x201F4E75;        /* MOVE (A7)+,<ea> */
  2469.       a[3] = 0;
  2470.       if(j > 7)
  2471.       {                 /* LEA x(A7),Ax */
  2472.     j -= 8;
  2473.     a[0] = 0x41EF0008 | (j << 25);
  2474.     a[2] += 0x400000;        /* set A flag */
  2475.       }
  2476.       else
  2477.       {                 /* MOVE.L A7,Dx  -- ADDQ.L #8,Dx */
  2478.     a[0] = 0x200F5080 | j | (j << 25);
  2479.       }
  2480.       a[2] += j << 25;
  2481.  
  2482.       DoOutputDirect(a, 14);
  2483.     }
  2484.     else
  2485.     {
  2486.       a[0] = HUNK_CODE; a[1] = 1;
  2487.       a[2] = 0x4EEE0000 + (UWORD) (- ap->Bias); /* JMP instruction */
  2488.       DoOutputDirect(a, 12);
  2489.     }
  2490.   }
  2491.   else
  2492.   {
  2493.     ULONG registers, offset = 1, pos = 4, l;
  2494.     UWORD data[100];                /* 200 byte data field */
  2495.  
  2496.     registers = GetRegisterData(ap);
  2497.  
  2498.     data[0] = 0;
  2499.     data[1] = HUNK_CODE;
  2500.     data[2] = 0;
  2501.     /* data[3] is size */
  2502.  
  2503.     if(!registers) /* happens only when !(ap->Flags & AMIPRAG_A6USE) */
  2504.     {
  2505.       data[pos++] = 0x2F0E;        /* MOVE.L A6,-(A7) */
  2506.       ++offset;                /* one long more on stack */
  2507.     }
  2508.     else
  2509.     {
  2510.       data[pos++] = 0x48E7;        /* MOVEM.L xxx,-(A7) */
  2511.       data[pos++] = registers;        /* storem MOVEM.L registers */
  2512.       for(l = (UWORD) registers; l; l >>= 1)
  2513.       {
  2514.         if(l & 1)
  2515.       ++offset;            /* get offset addition */
  2516.       }
  2517.     }
  2518.  
  2519.     if(!(ap->Flags & AMIPRAGFLAG_A6USE)) /* store library base in A6 */
  2520.     {
  2521.       data[pos++] = 0x2C6F;        /* MOVE.L ofs(A7),A6 */
  2522.       data[pos++] = (offset++) << 2;
  2523.     }
  2524.  
  2525.     pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
  2526.  
  2527.     /* here comes the base reference */
  2528.     data[pos++] = 0x4EAE;        /* JSR xxx(A6) */
  2529.     data[pos++] = -ap->Bias;        /* JSR offset */
  2530.     if(registers)
  2531.     {
  2532.       data[pos++] = 0x4CDF;        /* MOVEM.L (A7)+,xxx */
  2533.       data[pos++] = (registers >> 16);    /* store MOVEM.L registers */
  2534.     }
  2535.     else
  2536.       data[pos++] = 0x2C5F;        /* MOVE.L (A7)+,A6 */
  2537.  
  2538.     data[pos++] = 0x4E75;        /* RTS */
  2539.  
  2540.     if(pos & 1)
  2541.       data[pos++] = 0;            /* round to long */
  2542.  
  2543.     data[3] = (pos-4)>>1;        /* store hunk len */
  2544.     DoOutputDirect(data, pos<<1);
  2545.   }
  2546.  
  2547.   a[0] = HUNK_EXT;
  2548.   DoOutputDirect(a,4);
  2549.  
  2550.   /* here come the XDEF name references */
  2551.  
  2552.   OutputXDEF("%s", name);    /* ASM names */
  2553.   OutputXDEF("LOC_%s", name);
  2554.  
  2555.   OutputXDEF("_%s", name);    /* C names */
  2556.   OutputXDEF("_LOC_%s", name);
  2557.  
  2558.   if(!ap->NumArgs && clibdata)
  2559.   {
  2560.     OutputXDEF("%s__%sP07Library", name, str2);    /* C++ names no parameters */
  2561.     OutputXDEF("LOC_%s__%sP07Library", name, str2);
  2562.   }
  2563.   else if((cd = GetClibFunc(name, ap, flags)))
  2564.   {
  2565.     UBYTE txt[100];
  2566.     ULONG ret = 0;
  2567.  
  2568.     do
  2569.     {
  2570.       if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
  2571.       {                 /* C++ names with parameters */
  2572.         if(!(ap->Flags & AMIPRAGFLAG_A6USE))
  2573.         {
  2574.           OutputXDEF("%s__%sP07Library%s", name, str2, txt);
  2575.       OutputXDEF("LOC_%s__%sP07Library%s", name, str2, txt);
  2576.     }
  2577.     else
  2578.     {
  2579.           OutputXDEF("%s__%s", name, txt);
  2580.       OutputXDEF("LOC_%s__%s", name, txt);
  2581.     }
  2582.       }
  2583.     } while(ret == 0xFFFFFFFF);
  2584.   }
  2585.  
  2586.   a[0] = 0; a[1] = HUNK_END;
  2587.  
  2588.   return DoOutputDirect(a, 8);
  2589. }
  2590.  
  2591. ULONG FuncLocText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2592. {
  2593.   struct ClibData *cd;
  2594.   LONG i;
  2595.  
  2596.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  2597.   {
  2598.     DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  2599.     return 1;
  2600.   }
  2601.  
  2602.   Flags |= FLAG_DONE; /* We did something */
  2603.  
  2604.   if(!(cd = GetClibFunc(name, ap, flags)))
  2605.     return 1;
  2606.  
  2607.   OutClibType(&cd->ReturnType, 0);
  2608.   DoOutput(" LOC_%s("/*)*/, name);
  2609.   if(!(ap->Flags & AMIPRAGFLAG_A6USE))
  2610.   {
  2611.     if(Flags & FLAG_LOCALREG)
  2612.       DoOutput("register __a6 ");
  2613.     DoOutput("struct Library * libbase");
  2614.     if(ap->NumArgs)
  2615.       DoOutput(", ");
  2616.   }
  2617.  
  2618.   if(ap->NumArgs)
  2619.   {
  2620.     for(i = 0; i < ap->NumArgs-1; i++)
  2621.     {
  2622.       if(((Flags & FLAG_LOCALREG &&
  2623.       !DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
  2624.       !OutClibType(&cd->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  2625.     return 0;
  2626.     }
  2627.  
  2628.     if(flags & FUNCFLAG_NORMAL)
  2629.     {
  2630.       if(((Flags & FLAG_LOCALREG &&
  2631.       !DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
  2632.       !OutClibType(&cd->Args[i], ap->Args[i].ArgName) ||
  2633.       !DoOutput(/*(*/");\n"))
  2634.         return 0;
  2635.       if(BaseName)
  2636.       {
  2637.         DoOutput("#define %s("/*)*/, name);
  2638.         for(i = 0; i < ap->NumArgs-1; ++i)
  2639.           DoOutput("%lc, ", (i+'a'));
  2640.         DoOutput(/*(*/"%lc) LOC_%s((struct Library *) %s, "/*)*/,(i+'a'),
  2641.         name, BaseName);
  2642.         for(i = 0; i < ap->NumArgs-1; ++i)
  2643.       DoOutput("%lc, ",(i+'a'));
  2644.         return DoOutput(/*(*/"%lc)\n\n",(i+'a'));
  2645.       }
  2646.     }
  2647.     else
  2648.       return DoOutput(/*(*/"...);\n");
  2649.   }
  2650.   else if(BaseName)
  2651.     return DoOutput(/*(*/");\n#define %s(a) LOC_%s((struct Library *) a)\n\n",
  2652.     name, name);
  2653.   else
  2654.     return DoOutput(/*(*/");\n");
  2655.   return 1;
  2656. }
  2657.  
  2658. ULONG FuncInline(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2659. {
  2660.   ULONG noret = 0, a45 = 0, i, j;
  2661.   LONG fp = -1;
  2662.   struct ClibData *cd;
  2663.  
  2664.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  2665.   {
  2666.     DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  2667.     return 1;
  2668.   }
  2669.  
  2670.   Flags |= FLAG_DONE; /* We did something */
  2671.  
  2672.   if(flags & FUNCFLAG_ALIAS)
  2673.   {
  2674.     DoOutput("#define %s("/*)*/, name);
  2675.     for(i = 0; i < ap->NumArgs-1; ++i)
  2676.       DoOutput("%s, ", ap->Args[i].ArgName);
  2677.     DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
  2678.     for(i = 0; i < ap->NumArgs-1; ++i)
  2679.       DoOutput("(%s), ", ap->Args[i].ArgName);
  2680.     return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
  2681.   }
  2682.  
  2683.   if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  2684.     return 1;
  2685.  
  2686.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  2687.     noret = 1; /* this is a void function */
  2688.  
  2689.   if(ap->Flags & AMIPRAGFLAG_A5USE)
  2690.     a45 = REG_A5;
  2691.   if(ap->Flags & AMIPRAGFLAG_A4USE)
  2692.   {
  2693.     if(a45)
  2694.     {
  2695.       DoError(ERR_INLINE_A4_AND_A5, ap->Line);
  2696.       return 1; /* skip this entry */
  2697.     }
  2698.     a45 = REG_A4;
  2699.   }
  2700.   if(a45 && (ap->Flags & AMIPRAGFLAG_D7USE))
  2701.   {
  2702.     DoError(ERR_INLINE_D7_AND_A45, ap->Line);
  2703.     return 1; /* skip this entry */
  2704.   }
  2705.  
  2706.   if((flags & FUNCFLAG_TAG))
  2707.   {
  2708.     if(!(Flags & FLAG_INLINESTUB)) /* no stubs */
  2709.     {
  2710.       DoOutput("#ifndef NO_%sINLINE_STDARG\n#define %s("/*)*/, 
  2711.       Flags & FLAG_POWERUP ? "PPC" : "", name);
  2712.       for(i = 0; i < ap->NumArgs-1; ++i)
  2713.       {
  2714.         DoOutput("%s, ", ap->Args[i].ArgName);
  2715.       }
  2716.       DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*}))*/,
  2717.       ap->FuncName);
  2718.       for(i = 0; i < ap->NumArgs-1; ++i)
  2719.         DoOutput("(%s), ", ap->Args[i].ArgName);
  2720.       DoOutput("("/*)*/);
  2721.       OutClibType(&cd->Args[i], 0);
  2722.       return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
  2723.     }
  2724.     else
  2725.       return FuncCSTUBS(ap, flags, name);
  2726.       /* call CSTUBS, as this equals the method used there */
  2727.   }
  2728.  
  2729.   if(Flags & FLAG_INLINENEW) /* new style */
  2730.   {
  2731.     STRPTR funcpar = "";
  2732.     DoOutput("#define %s("/*)*/, name);
  2733.  
  2734.     for(i = 0; i < cd->NumArgs; ++i)
  2735.     {
  2736.       if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
  2737.         funcpar = "FP";
  2738.     }
  2739.  
  2740.     if(ap->NumArgs)
  2741.     {
  2742.       for(i = 0; i < ap->NumArgs-1; ++i)
  2743.         DoOutput("%s, ", ap->Args[i].ArgName);
  2744.       DoOutput("%s", ap->Args[i].ArgName);
  2745.     }
  2746.     DoOutput(/*(*/") \\\n\tLP%ld%s%s%s%s(0x%lx, "/*)*/, ap->NumArgs,
  2747.     (noret ? "NR" : ""), (a45 ? RegNamesUpper[a45] : (STRPTR) ""),
  2748.     (BaseName ? "" : "UB"), funcpar, ap->Bias);
  2749.     if(!noret)
  2750.     {
  2751.       OutClibType(&cd->ReturnType, 0);
  2752.       DoOutput(", ");
  2753.     }
  2754.     DoOutput("%s, ", name);
  2755.  
  2756.     for(i = 0; i < ap->NumArgs; ++i)
  2757.     {
  2758.       j = ap->Args[i].ArgReg;
  2759.       if(a45 && (j == REG_A4 || j == REG_A5))
  2760.         j = REG_D7;
  2761.       if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
  2762.       {
  2763.         DoOutput("__fpt"); fp = i;
  2764.       }
  2765.       else
  2766.         OutClibType(&cd->Args[i], 0);
  2767.   
  2768.       DoOutput(", %s, %s%s", ap->Args[i].ArgName, RegNames[j],
  2769.       (i == ap->NumArgs-1 && !BaseName ? "" : ", "));
  2770.     }
  2771.  
  2772.     if(BaseName) /* was "##base" used? */
  2773.       DoOutput("\\\n\t, %s_BASE_NAME", ShortBaseNameUpper);
  2774.  
  2775.     if(fp >= 0)
  2776.     {
  2777.       DoOutput(", ");
  2778.       OutClibType(&cd->Args[fp], "__fpt");
  2779.     }
  2780.  
  2781.     if(Flags & FLAG_POWERUP)
  2782.       DoOutput(", IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0");
  2783.  
  2784.     return DoOutput(/*(*/")\n\n");
  2785.   }
  2786.  
  2787.   /* old mode or stubs mode */
  2788.  
  2789.   DoOutput("%s%s__inline ", Flags & FLAG_INLINESTUB ? "" : "extern ",
  2790.   Flags & FLAG_POWERUP ? "static " : "");
  2791.   OutClibType(&cd->ReturnType, 0);
  2792.   DoOutput("\n%s(%s"/*)*/, name, (BaseName ?
  2793.   (ap->NumArgs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  2794.  
  2795.   for(i = 0; i < ap->NumArgs; ++i)
  2796.   {
  2797.     OutClibType(&cd->Args[i], ap->Args[i].ArgName);
  2798.     if(i < ap->NumArgs-1)
  2799.       DoOutput(", ");
  2800.   }
  2801.  
  2802.   if(Flags & FLAG_POWERUP)
  2803.   {
  2804.     DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
  2805.     "\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
  2806.     "/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
  2807.     "/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
  2808.     "\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
  2809.     "/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
  2810.     "/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
  2811.  
  2812.     if(ap->NumArgs)
  2813.     {
  2814.       for(i = 0; i < ap->NumArgs; ++i)
  2815.       {
  2816.         DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
  2817.         RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
  2818.       }
  2819.     }
  2820.  
  2821.     DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
  2822.  
  2823.     if(BaseName)
  2824.       DoOutput("\tMyCaos.a6\t\t= (ULONG) %s_BASE_NAME;\n", ShortBaseNameUpper);
  2825.     if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  2826.       DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
  2827.     else
  2828.     {
  2829.       DoOutput("\treturn(("/*))*/);
  2830.       OutClibType(&cd->ReturnType, 0);
  2831.       DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
  2832.     }
  2833.     return Output_Error;
  2834.   }
  2835.  
  2836.   DoOutput(/*(*/")\n{\n%s"/*}*/, (BaseName ? "   BASE_EXT_DECL\n" : ""));
  2837.  
  2838.   if(!noret)
  2839.   {
  2840.     DoOutput("   register ");
  2841.     OutClibType(&cd->ReturnType, "res");
  2842.     DoOutput(" __asm(\"d0\");\n");
  2843.   }
  2844.  
  2845.   if(BaseName)
  2846.     DoOutput("   register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
  2847.     GetBaseType());
  2848.  
  2849.   for(i = 0; i < ap->NumArgs; ++i)
  2850.   {
  2851.     j = ap->Args[i].ArgReg;
  2852.     if(a45 && (j == REG_A4 || j == REG_A5))
  2853.       j = REG_D7;
  2854.  
  2855.     DoOutput("   register ");
  2856.     OutClibType(&cd->Args[i], RegNames[j]);
  2857.     DoOutput(" __asm(\"%s\") = %s;\n", RegNames[j], ap->Args[i].ArgName);
  2858.   }
  2859.  
  2860.   if(a45)
  2861.   {
  2862.     DoOutput("   __asm volatile (\"exg d7,%s\\n\\t"/*)*/
  2863.     "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", RegNames[a45],
  2864.     ap->Bias, RegNames[a45]);
  2865.   }
  2866.   else
  2867.     DoOutput("   __asm volatile (\"jsr a6@(-0x%lx:W)\"\n"/*)*/, ap->Bias);
  2868.  
  2869.   DoOutput(noret ? "   : /* No Output */\n" : "   : \"=r\" (res)\n");
  2870.  
  2871.   DoOutput("   : ");
  2872.   if(BaseName)
  2873.     DoOutput("\"r\" (a6)%s", (ap->NumArgs ? ", ": ""));
  2874.  
  2875.   for(i = 0; i < ap->NumArgs; ++i)
  2876.   {
  2877.     j = ap->Args[i].ArgReg;
  2878.     if(a45 && (j == REG_A4 || j == REG_A5))
  2879.       j = REG_D7;
  2880.  
  2881.     DoOutput("\"r\" (%s)%s", RegNames[j], (i < ap->NumArgs-1 ? ", " : ""));
  2882.   }
  2883.  
  2884.   DoOutput("\n   : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
  2885.  
  2886.   if(noret)
  2887.     return DoOutput(/*({*/", \"cc\", \"memory\");\n}\n\n");
  2888.   else
  2889.     return DoOutput(/*({*/", \"cc\", \"memory\");\n   return res;\n}\n\n");
  2890. }
  2891.  
  2892. ULONG FuncPowerUP(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2893. {
  2894.   ULONG i;
  2895.   struct ClibData *cd;
  2896.  
  2897.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  2898.   {
  2899.     DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  2900.     return 1;
  2901.   }
  2902.  
  2903.   Flags |= FLAG_DONE; /* We did something */
  2904.  
  2905.   if(flags & FUNCFLAG_ALIAS)
  2906.   {
  2907.     DoOutput("#define %s("/*)*/, name);
  2908.     for(i = 0; i < ap->NumArgs-1; ++i)
  2909.       DoOutput("%s, ", ap->Args[i].ArgName);
  2910.     DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
  2911.     for(i = 0; i < ap->NumArgs-1; ++i)
  2912.       DoOutput("(%s), ", ap->Args[i].ArgName);
  2913.     return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
  2914.   }
  2915.  
  2916.   if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  2917.     return 1;
  2918.  
  2919.   if(flags & FUNCFLAG_TAG)
  2920.   {
  2921.     DoOutput("#ifndef NO_PPCINLINE_STDARG\n#define %s("/*)*/, name);
  2922.     for(i = 0; i < ap->NumArgs-1; ++i)
  2923.       DoOutput("%s, ", ap->Args[i].ArgName);
  2924.     DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*)})*/,
  2925.     ap->FuncName);
  2926.     for(i = 0; i < ap->NumArgs-1; ++i)
  2927.       DoOutput("(%s), ", ap->Args[i].ArgName);
  2928.     DoOutput("("/*)*/);
  2929.     OutClibType(&cd->Args[i], 0);
  2930.     return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
  2931.   }
  2932.  
  2933.   DoOutput("#define\t%s("/*)*/, name);
  2934.  
  2935.   if(ap->NumArgs)
  2936.   {
  2937.   
  2938.     for(i = 0; i < ap->NumArgs-1; ++i)
  2939.       DoOutput("%s, ", ap->Args[i].ArgName);
  2940.     DoOutput(/*(*/"%s)\t_%s("/*)*/, ap->Args[i].ArgName, name);
  2941.  
  2942.     if(BaseName)
  2943.       DoOutput("%s_BASE_NAME, ", ShortBaseNameUpper);
  2944.  
  2945.     for(i = 0; i < ap->NumArgs-1; ++i)
  2946.       DoOutput("%s, ", ap->Args[i].ArgName);
  2947.     DoOutput(/*(*/"%s)\n\n", ap->Args[i].ArgName);
  2948.   }
  2949.   else if(BaseName)
  2950.     DoOutput(/*(*/")\t_%s(%s_BASE_NAME)\n\n", name, ShortBaseNameUpper);
  2951.   else
  2952.     DoOutput(/*(*/")\t_%s()\n\n", name);
  2953.  
  2954.   DoOutput("static __inline ");
  2955.   OutClibType(&cd->ReturnType, 0);
  2956.   
  2957.   DoOutput("\n_%s("/*)*/, name);
  2958.   if(BaseName)
  2959.     DoOutput("void * %s%s", BaseName, ap->NumArgs ? ", " : "");
  2960.  
  2961.   for(i = 0; i < ap->NumArgs; ++i)
  2962.   {
  2963.     OutClibType(&cd->Args[i], ap->Args[i].ArgName);
  2964.     if(i < ap->NumArgs-1)
  2965.       DoOutput(", ");
  2966.   }
  2967.  
  2968.   DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
  2969.     "\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
  2970.     "/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
  2971.     "/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
  2972.     "\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
  2973.     "/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
  2974.     "/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
  2975.  
  2976.   if(ap->NumArgs)
  2977.   {
  2978.     for(i = 0; i < ap->NumArgs; ++i)
  2979.     {
  2980.       DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
  2981.       RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
  2982.     }
  2983.   }
  2984.  
  2985.   DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
  2986.  
  2987.   if(BaseName)
  2988.     DoOutput("\tMyCaos.a6\t\t= (ULONG) %s;\n", BaseName);
  2989.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  2990.     DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
  2991.   else
  2992.   {
  2993.     DoOutput("\treturn(("/*))*/);
  2994.     OutClibType(&cd->ReturnType, 0);
  2995.     DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
  2996.   }
  2997.   return Output_Error;
  2998. }
  2999.  
  3000. ULONG FuncFPCUnit(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3001. {
  3002.   LONG i;
  3003.   struct ClibData *cd;
  3004.  
  3005.   if(ap->Flags & AMIPRAGFLAG_ARGCOUNT)
  3006.   {
  3007.     DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  3008.     return 1;
  3009.   }
  3010.   else if(ap->Flags & AMIPRAGFLAG_FLOATARG)
  3011.   {
  3012.     /* this error was done already */
  3013. /*    DoError(ERR_FLOATARG_NOT_ALLOWED, ap->Line); */
  3014.     return 1;
  3015.   }
  3016.   else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3017.     return 1;
  3018.  
  3019.   if(!FuncFPCType(ap, flags, name))
  3020.     return 0;
  3021.  
  3022.   DoOutput("BEGIN\n  ASM\n\tMOVE.L\tA6,-(A7)\n");
  3023.  
  3024.   for(i = 0; i < ap->NumArgs; ++i)
  3025.     DoOutput("\tMOVE%s.L\t%s,%s\n", ap->Args[i].ArgReg >= REG_A0 ? "A" : "",
  3026.     ap->Args[i].ArgName, RegNamesUpper[ap->Args[i].ArgReg]);
  3027.  
  3028.   DoOutput("\tMOVEA.L\t%s,A6\n\tJSR\t-%03ld(A6)\n\tMOVEA.L\t(A7)+,A6\n",
  3029.   BaseName, ap->Bias);
  3030.  
  3031.   if(!IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3032.   {
  3033.     if(!cd->ReturnType.PointerDepth &&
  3034.     cd->ReturnType.Flags == CPP_FLAG_BOOLEAN)
  3035.       DoOutput("\tTST.W\tD0\n\tBEQ.B\t@end\n\tMOVEQ\t#1,D0\n"
  3036.       "  @end:\tMOVE.B\tD0,@RESULT\n");
  3037.     else
  3038.       DoOutput("\tMOVE.L\tD0,@RESULT\n");
  3039.   }
  3040.   return DoOutput("  END;\nEND;\n\n");
  3041. }
  3042.  
  3043. ULONG FuncFPCType(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3044. {
  3045.   ULONG ret = 1;
  3046.   LONG i;
  3047.   struct ClibData *cd;
  3048.  
  3049.   if(ap->Flags & AMIPRAGFLAG_FLOATARG)
  3050.   {
  3051.     DoError(ERR_FLOATARG_NOT_ALLOWED, ap->Line);
  3052.     return 1;
  3053.   }
  3054.   else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3055.     return 1;
  3056.  
  3057.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3058.   {
  3059.     ret = 0; DoOutput("PROCEDURE %s", name);
  3060.   }
  3061.   else
  3062.     DoOutput("FUNCTION %s", name);
  3063.  
  3064.   if(ap->NumArgs)
  3065.   {
  3066.     DoOutput("("/*)*/);
  3067.     for(i = 0; i < ap->NumArgs;)
  3068.     {
  3069.       OutPASCALType(&cd->Args[i], ap->Args[i].ArgName, 0);
  3070.       if(++i != ap->NumArgs)
  3071.         DoOutput("; ");
  3072.     }
  3073.     DoOutput(/*(*/")");
  3074.   }
  3075.  
  3076.   if(ret)
  3077.     OutPASCALType(&cd->ReturnType, "", 1);
  3078.  
  3079.   Flags |= FLAG_DONE; /* We did something */
  3080.  
  3081.   return DoOutput(";\n");
  3082. }
  3083.  
  3084. ULONG FuncBMAP(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3085. {
  3086.   UBYTE reg, i;
  3087.  
  3088.   Flags |= FLAG_DONE; /* We did something */
  3089.  
  3090.   if(ap->Flags & AMIPRAGFLAG_FLOATARG)
  3091.   {
  3092.     DoError(ERR_FLOATARG_NOT_ALLOWED, ap->Line);
  3093.     return 1;
  3094.   }
  3095.   else if(ap->Flags & AMIPRAGFLAG_A6USE)
  3096.   {
  3097.     DoError(ERR_A6_NOT_ALLOWED, ap->Line);
  3098.     return 0;
  3099.   }
  3100.   else if(ap->Flags & AMIPRAGFLAG_A5USE)
  3101.   {
  3102.     DoError(ERR_A5_NOT_ALLOWED, ap->Line);
  3103.     return 0;
  3104.   }
  3105.  
  3106.   for(i = 0; BMAPSpecial[i]; ++i)
  3107.   {
  3108.     if(!stricmp(name, BMAPSpecial[i]))
  3109.     {
  3110.       DoOutput("x"); break;
  3111.     }
  3112.   }
  3113.  
  3114.   DoOutput(name);
  3115.   reg = 0;            DoOutputDirect(®, 1);
  3116.   reg = (-ap->Bias)>>8;        DoOutputDirect(®, 1);
  3117.   reg = -ap->Bias;        DoOutputDirect(®, 1);
  3118.   for(i = 0; i < ap->NumArgs; ++i)
  3119.   {
  3120.     reg = 1+ap->Args[i].ArgReg;    DoOutputDirect(®, 1);
  3121.   }
  3122.   reg = 0;
  3123.   return DoOutputDirect(®, 1);
  3124. }
  3125.  
  3126. ULONG CallFunc(ULONG tagmode, STRPTR comment, FuncType Func)
  3127. {
  3128.   struct Comment *com = 0;
  3129.   struct AmiPragma *ap;
  3130.  
  3131.   if(comment)
  3132.     com = (struct Comment *) Comment.First;
  3133.  
  3134.   for(ap = (struct AmiPragma *) AmiPragma.First; ap && !CTRL_C;
  3135.   ap = (struct AmiPragma *) ap->List.Next)
  3136.   {
  3137.     if(BaseName && (ap->Flags & AMIPRAGFLAG_A6USE))
  3138.     {
  3139.       DoError(ERR_A6_NOT_ALLOWED, ap->Line);
  3140.     }
  3141.     else if((ap->Flags & AMIPRAGFLAG_PUBLIC) || (Flags & FLAG_PRIVATE))
  3142.     {
  3143.       while(com && com->Bias <= ap->Bias)
  3144.       {
  3145.     if(!DoOutput(comment, com->Data))
  3146.       return 0;
  3147.     com = (struct Comment *) com->List.Next;
  3148.       }
  3149.  
  3150. #ifdef DEBUG_OLD
  3151.   Printf("Processing %s\n", ap->FuncName);
  3152. #endif
  3153.  
  3154.       if(tagmode != TAGMODE_TAGS && ap->FuncName &&
  3155.       !Func(ap, FUNCFLAG_NORMAL, ap->FuncName))
  3156.     return 0;
  3157.       if(ap->AliasName &&
  3158.       (((ap->AliasName->Type & FUNCFLAG_TAG) && tagmode) ||
  3159.       (!(ap->AliasName->Type & FUNCFLAG_TAG) && tagmode != TAGMODE_TAGS)) &&
  3160.       !Func(ap, FUNCFLAG_ALIAS|ap->AliasName->Type, ap->AliasName->AliasName))
  3161.     return 0;
  3162.       if(tagmode && ap->TagName && !Func(ap, FUNCFLAG_TAG, ap->TagName))
  3163.     return 0;
  3164.     }
  3165.   }
  3166.   while(com)
  3167.   {
  3168.     if(!DoOutput(comment, com->Data))
  3169.       return 0;
  3170.     com = (struct Comment *) com->List.Next;
  3171.   }
  3172.   return 1;
  3173. }
  3174.  
  3175. /* ------------------------------------------------------------------ */
  3176.  
  3177. LONG AddClibEntry(STRPTR buffer, STRPTR bufend, ULONG linenum)
  3178. {
  3179.   STRPTR buf = buffer;
  3180.   struct ClibData d, *f;
  3181.  
  3182.   memset(&d, 0, sizeof(struct ClibData));
  3183.   if(!GetCPPType(&d.ReturnType, SkipBlanks(buf)))
  3184.   {
  3185.     DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, 0);
  3186.     return 0;
  3187.   }
  3188.   d.FuncName = SkipBlanks(d.ReturnType.TypeStart+d.ReturnType.FullLength);
  3189.   while(*(buf++) != '('/*)*/)
  3190.     ;
  3191.   *(SkipName(d.FuncName)) = 0;
  3192.   buf = SkipBlanksRet(buf);
  3193.  
  3194.   while(*buf != /*(*/')' && buf < bufend)
  3195.   {
  3196.     if(!GetCPPType(&d.Args[d.NumArgs++], buf))
  3197.     {
  3198.       DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, d.NumArgs);
  3199.       return 0;
  3200.     }
  3201.  
  3202.     buf += d.Args[d.NumArgs-1].FullLength;
  3203.     while(*buf != ',' && *buf != /*(*/')' && buf < bufend)
  3204.       ++buf;
  3205. #ifdef DEBUG_OLD
  3206.   Printf("Added argument %ld for %s (%ld bytes)\n", d.NumArgs, d.FuncName,
  3207.   d.Args[d.NumArgs-1].FullLength);
  3208. #endif
  3209.     if(*buf == ',')
  3210.       buf = SkipBlanksRet(++buf);
  3211.   }
  3212.  
  3213.   if(d.NumArgs == 1 && IsCPPType(&d.Args[0], CPP_TYPE_VOID))
  3214.     d.NumArgs = 0; /* void arguments are no arguments */
  3215.  
  3216.   if(!(f = (struct ClibData *) AllocListMem(sizeof(struct ClibData))))
  3217.     return -1;
  3218.  
  3219.   CopyMem(&d, f, sizeof(struct ClibData));
  3220.  
  3221.   if(!clibdata)
  3222.     clibdata = f;
  3223.   else
  3224.   {
  3225.     struct ClibData *e = clibdata;
  3226.     while(e->Next)
  3227.       e = e->Next;
  3228.     e->Next = f;
  3229.   }
  3230.  
  3231. #ifdef DEBUG
  3232.   Printf("Added prototype for %s (line %ld, %ld bytes) with %ld args\n",
  3233.   f->FuncName, linenum, buf-buffer, f->NumArgs);
  3234. #endif
  3235.   return buf-buffer;
  3236. }
  3237.  
  3238. LONG ScanClibFile(STRPTR buf, STRPTR bufend)
  3239. {
  3240.   STRPTR linestart = buf;
  3241.   ULONG linenum = 1;
  3242.  
  3243.   while(buf < bufend && !CTRL_C)
  3244.   {
  3245.     if(*buf == '/' && buf[1] == '*')
  3246.     {
  3247.       while(buf < bufend && (*buf != '*' || buf[1] != '/'))
  3248.       {
  3249.         if(*(buf++) == '\n')
  3250.         {
  3251.           ++linenum; linestart = buf;
  3252.         } /* skip comments */
  3253.       }
  3254.     }
  3255.     else if(*buf == '/' && buf[1] == '/')
  3256.     {
  3257.       while(buf < bufend && *buf != '\n')
  3258.         ++buf; /* skip line comments */
  3259.     }
  3260.     else if(*buf == '\n')
  3261.     {
  3262.       linestart = ++buf; ++linenum;
  3263.     }
  3264.     else if(*buf == '('/*)*/)
  3265.     {
  3266.       LONG i;
  3267.  
  3268.       if((i = AddClibEntry(linestart, bufend, linenum)) == -1) /* no memory */
  3269.         return 0;
  3270.       else if(!i)
  3271.       {
  3272.         while(buf < bufend && *buf != '\n')
  3273.           ++buf; /* skip this line */
  3274.       }
  3275.       else
  3276.       {
  3277.         i -= buf-linestart;
  3278.         while(buf < bufend && i-- > 0)
  3279.         {
  3280.           if(*(buf++) == '\n')
  3281.           {
  3282.             linestart = buf;
  3283.             ++linenum;
  3284.           } /* skip this function */
  3285.         }
  3286.       }
  3287.     }
  3288.     else
  3289.       ++buf;
  3290.   } /* while */
  3291.   return 1;
  3292. }
  3293.  
  3294. LONG IsCPPType(struct CPP_NameType *data, UBYTE type)
  3295. {
  3296.   if(!data || data->Flags || data->Type != type || data->PointerDepth)
  3297.     return 0;
  3298.   return type;
  3299. }
  3300.  
  3301. LONG GetCPPType(struct CPP_NameType *data, STRPTR start)
  3302. {
  3303.   ULONG ok = 1;
  3304.   STRPTR u;
  3305.  
  3306.   data->TypeStart = SkipBlanks(start);
  3307.  
  3308.   do
  3309.   {
  3310.     start = SkipBlanks((u = start));
  3311.     if(!strncmp("...",start,3))
  3312.     {
  3313.       data->Type = CPP_TYPE_VARARGS; return 1;
  3314.     }
  3315.     if(CheckKeyword(start, "const", 5))
  3316.     {
  3317.       data->Flags |= CPP_FLAG_CONST; start += 6;
  3318.     }
  3319.     else if(CheckKeyword(start, "signed", 6))
  3320.       start += 7;
  3321.     else if(CheckKeyword(start, "unsigned", 8))
  3322.     {
  3323.       data->Flags |= CPP_FLAG_UNSIGNED; start += 9;
  3324.     }
  3325.     else if(CheckKeyword(start, "struct", 6))
  3326.     {
  3327.       start = SkipBlanks(start+6);
  3328.       data->Flags |= CPP_FLAG_STRUCT;
  3329.       if(*start != '?') /* ? for external types */
  3330.       {
  3331.         start = SkipName((data->StructureName = start));
  3332.         data->StructureLength = start-data->StructureName;
  3333.       }
  3334.       else
  3335.       {
  3336.     data->StructureLength = 0;
  3337.     data->StructureName = "";
  3338.     ++start;
  3339.       }
  3340.     }
  3341.     else if(CheckKeyword(start, "union", 5))
  3342.     {
  3343.       start = SkipBlanks(start+5);
  3344.       data->Flags |= CPP_FLAG_UNION;
  3345.       if(*start != '?') /* ? for external types */
  3346.       {
  3347.         start = SkipName((data->StructureName = start));
  3348.         data->StructureLength = start-data->StructureName;
  3349.       }
  3350.       else
  3351.       {
  3352.     data->StructureLength = 0;
  3353.     data->StructureName = "";
  3354.     ++start;
  3355.       }
  3356.     }
  3357.     else if(CheckKeyword(start, "enum", 4))
  3358.     {
  3359.       start = SkipBlanks(start+4);
  3360.       data->Flags |= CPP_FLAG_ENUM;
  3361.       if(*start != '?') /* ? for external types */
  3362.       {
  3363.         start = SkipName((data->StructureName = start));
  3364.         data->StructureLength = start-data->StructureName;
  3365.       }
  3366.       else
  3367.       {
  3368.     data->StructureLength = 0;
  3369.     data->StructureName = "";
  3370.     ++start;
  3371.       }
  3372.     }
  3373.     else if(*start == '*')
  3374.     {
  3375.       ++start; ++data->PointerDepth;
  3376.     }
  3377.     else
  3378.     {
  3379.       ULONG i;
  3380.  
  3381.       for(i = 0; CPP_Field[i].Text; ++i)
  3382.       {
  3383.     if(!strncmp(start, CPP_Field[i].Text, CPP_Field[i].Length) &&
  3384.     (start[CPP_Field[i].Length] == ' ' ||
  3385.     start[CPP_Field[i].Length] == '\t' ||
  3386.     start[CPP_Field[i].Length] == '\n' ||
  3387.         start[CPP_Field[i].Length] == ',' ||
  3388.         start[CPP_Field[i].Length] == /*(*/')' ||
  3389.         start[CPP_Field[i].Length] == '('/*)*/ ||
  3390.           start[CPP_Field[i].Length] == '*'))
  3391.     {
  3392.       start += CPP_Field[i].Length;
  3393.       data->Type = CPP_Field[i].Type;
  3394.       data->Flags |= CPP_Field[i].Flags;
  3395.       if(CPP_Field[i].Flags & CPP_FLAG_POINTER)
  3396.         ++data->PointerDepth;
  3397.       break;
  3398.     }
  3399.       }
  3400.       if(CPP_Field[i].Text)
  3401.         continue;
  3402.       else if(extnames)
  3403.       {
  3404.         struct CPP_ExternNames *a = extnames;
  3405.        
  3406.         while(a)
  3407.         {
  3408.           i = strlen(a->Type);
  3409.           if(!strncmp(a->Type, start, i) && !isalnum(start[i]) && 
  3410.           start[i] != '_')
  3411.           {
  3412.             start += i;
  3413.             data->StructureName = a->NameType.StructureName;
  3414.           data->FuncArgs = a->NameType.FuncArgs;
  3415.         data->StructureLength = a->NameType.StructureLength;
  3416.         data->PointerDepth += a->NameType.PointerDepth;
  3417.         data->Type = a->NameType.Type;
  3418.         data->Flags |= a->NameType.Flags;
  3419.         break;
  3420.           }
  3421.      
  3422.       /* check types here */
  3423.           a = a->Next;
  3424.         }
  3425.         if(a)
  3426.           continue;
  3427.       }
  3428.       break;
  3429.     }
  3430.   } while(1);
  3431.  
  3432.   if(start != SkipBlanks(u)) /* we broke the loop after increasing start */
  3433.     u = start;
  3434.  
  3435.   data->TypeLength = u - (data->TypeStart);
  3436.   data->FullLength = data->TypeLength;
  3437.  
  3438.   u = SkipBlanks(u);
  3439.  
  3440.   if(*u == '('/*)*/)
  3441.   {
  3442.     ok = 0;
  3443.     u = SkipBlanks(++u);
  3444.     if(*u == '*')
  3445.     {
  3446.       u = SkipBlanks(SkipName(SkipBlanks(++u)));
  3447.       if(*u == /*(*/')')
  3448.       {
  3449.         u = SkipBlanks(++u);
  3450.         if(*u == '('/*)*/)
  3451.         {
  3452.           data->Flags |= CPP_FLAG_FUNCTION;
  3453.           data->FuncArgs = u;
  3454.           ok = 1;
  3455.           u = SkipBlanks(++u);
  3456.           if(*u == /*(*/')')
  3457.             data->FuncArgs = 0;
  3458.       else
  3459.       {
  3460.         ULONG d = 0;
  3461.         while(d || *u != /*(*/')')
  3462.         {
  3463.           if(*u == '('/*)*/)
  3464.             ++d;
  3465.           else if(*u == /*(*/')')
  3466.             --d;
  3467.           ++u;
  3468.         }
  3469.         data->ArgsLength = u+1 - (data->FuncArgs);
  3470.       }
  3471.           data->FullLength = u+1 - (data->TypeStart);
  3472.         }
  3473.       }
  3474.     }
  3475.   }
  3476.  
  3477.   if(data->PointerDepth)
  3478.     data->Flags |= CPP_FLAG_POINTER;
  3479.  
  3480.   if((!data->Type && !data->Flags) || !ok)
  3481.     return 0;
  3482.   return 1;
  3483. }
  3484.  
  3485. struct ClibData *GetClibFunc(STRPTR name, struct AmiPragma *ap, ULONG flags)
  3486. {
  3487.   struct ClibData *d = clibdata;
  3488.  
  3489.   while(d && strcmp(name, d->FuncName))
  3490.     d = d->Next;
  3491.  
  3492.   if(!d)
  3493.   {
  3494.     if(!(ap->Flags & AMIPRAGFLAG_NOCLIB))
  3495.     {
  3496.       DoError(ERR_PROTOTYPE_MISSING, 0, name);
  3497.       ap->Flags |= AMIPRAGFLAG_NOCLIB;
  3498.     }
  3499.   }
  3500.   else if(ap->CallArgs != d->NumArgs && (!(flags & FUNCFLAG_TAG) ||
  3501.   ap->CallArgs+1 != d->NumArgs))
  3502.   {
  3503.     if(!(ap->Flags & (AMIPRAGFLAG_CLIBARGCNT|AMIPRAGFLAG_DIDWARN)))
  3504.     {
  3505.       DoError(ERR_CLIB_ARG_COUNT, 0, name, d->NumArgs, ap->NumArgs);
  3506.       ap->Flags |= AMIPRAGFLAG_CLIBARGCNT;
  3507.     }
  3508.     return 0;
  3509.   }
  3510.  
  3511.   return d;  
  3512. }
  3513.  
  3514. LONG CheckKeyword(STRPTR string, STRPTR keyword, LONG size)
  3515. {
  3516.   if(!strncmp(string, keyword, size))
  3517.   {
  3518.     string += size;
  3519.     if(*string == ' ' || *string == '\t' || *string == '\n')
  3520.       return size;
  3521.   }
  3522.   return 0;
  3523. }
  3524.  
  3525. /* return non zero, when ok, return 0xFFFFFFFF when STRPTR and not flags */
  3526. ULONG CopyCPPType(STRPTR buffer, ULONG flag, struct ClibData *cd,
  3527. struct AmiArgs *args)
  3528. {
  3529. /* when flag, then STRPTR is unsigned char * mode, else signed char * */
  3530.   ULONG ret = 1;
  3531.   ULONG i, j, k = 0;
  3532.  
  3533.   for(i = 0; i < cd->NumArgs; ++i)
  3534.   {
  3535.     struct CPP_NameType *nt;
  3536.  
  3537.     nt = &cd->Args[i];
  3538.  
  3539.     if(!flag && (nt->Flags & CPP_FLAG_STRPTR))
  3540.       ret = 0xFFFFFFFF;
  3541.  
  3542.     if(args && (Flags & FLAG_LOCALREG) && (nt->Type != CPP_TYPE_VARARGS))
  3543.     {
  3544.       *(buffer++) = CPP_TYPE_REGISTER;
  3545.       *(buffer++) = args[k].ArgReg + (args[k].ArgReg < 10 ? '0' : 'A'-10);
  3546.     }
  3547.     if(nt->Flags & CPP_FLAG_FUNCTION)
  3548.     {
  3549.       *(buffer++) = CPP_TYPE_POINTER; *(buffer++) = CPP_TYPE_FUNCTION;
  3550.     }
  3551.     for(j = 0; j < nt->PointerDepth; ++j)
  3552.       *(buffer++) = CPP_TYPE_POINTER;
  3553.     if(nt->Flags & CPP_FLAG_CONST)
  3554.       *(buffer++) = CPP_TYPE_CONST;
  3555.     if((nt->Flags & CPP_FLAG_UNSIGNED) &&
  3556.     !(flag && (nt->Flags & CPP_FLAG_STRPTR)))
  3557.       *(buffer++) = CPP_TYPE_UNSIGNED;
  3558.     if(nt->Flags & CPP_FLAG_ENUM)
  3559.       *(buffer++) = CPP_TYPE_ENUM;
  3560.     if(nt->Type)
  3561.       *(buffer++) = cd->Args[i].Type;
  3562.     else
  3563.     {
  3564.       ULONG i;
  3565.       sprintf(buffer, "%02ld", (ULONG) nt->StructureLength); buffer += 2;
  3566.       for(i = 0; i < nt->StructureLength; ++i)
  3567.     *(buffer++) = nt->StructureName[i];
  3568.     }
  3569.     if(nt->Flags & CPP_FLAG_FUNCTION)
  3570.     {
  3571. //      if(nt.FuncArgs)
  3572. //      {
  3573. //        ******** do something here
  3574. //        while(*buffer)
  3575. //          ++buffer;
  3576. //      }
  3577.       *(buffer++) = CPP_TYPE_FUNCEND;
  3578.     }
  3579.     ++k;
  3580.     if(IsCPPType(nt, CPP_TYPE_DOUBLE))    /* double needs 2 registers */
  3581.       ++k;
  3582.   }
  3583.  
  3584.   *(buffer) = 0;
  3585.  
  3586.   return ret;
  3587. }
  3588.  
  3589. ULONG OutClibType(struct CPP_NameType *nt, STRPTR txt)
  3590. {
  3591.   DoOutputDirect(nt->TypeStart, nt->TypeLength);
  3592.   if(!DoOutput((nt->Flags & CPP_FLAG_FUNCTION) ? (txt ? " (*%s)" : " (*)") :
  3593.   (txt ? " %s" : ""), txt))
  3594.     return 0;
  3595.  
  3596.   if(nt->Flags & CPP_FLAG_FUNCTION)
  3597.   {
  3598.     if(nt->FuncArgs)
  3599.       DoOutputDirect(nt->FuncArgs, nt->ArgsLength);
  3600.     else
  3601.       return DoOutput("()");
  3602.   }
  3603.  
  3604.   return 1;
  3605. }
  3606.  
  3607. ULONG OutPASCALType(struct CPP_NameType *t, STRPTR txt, ULONG ret)
  3608. {
  3609.   LONG i = t->PointerDepth;
  3610.  
  3611.   if(t->Flags & CPP_FLAG_CONST)
  3612.     DoOutput("CONST ");
  3613.   if(!ret && i == 1 &&
  3614.   (t->Type == CPP_TYPE_LONG || t->Type == CPP_TYPE_WORD))
  3615.   {
  3616.     DoOutput("VAR "); --i;
  3617.   }
  3618.  
  3619.   DoOutput("%s : ", txt);
  3620.  
  3621.   if(!i && t->Flags == CPP_FLAG_BOOLEAN)
  3622.     return DoOutput("BOOLEAN");
  3623.   else if(i && t->Type == CPP_TYPE_VOID)
  3624.     return DoOutput("POINTER");
  3625.   else if(t->Flags & CPP_FLAG_FUNCTION)
  3626.     return DoOutput("tPROCEDURE");
  3627.  
  3628.   while(i--)
  3629.     DoOutput("p");
  3630.  
  3631.   if((t->Flags & (CPP_FLAG_STRUCT|CPP_FLAG_UNION)) && t->StructureLength)
  3632.   {
  3633.     if(!t->PointerDepth)
  3634.       DoOutput("t");
  3635.     return DoOutputDirect(t->StructureName, t->StructureLength);
  3636.   }
  3637.  
  3638.   if(t->Flags & CPP_FLAG_UNSIGNED)
  3639.   {
  3640.     if(t->Type == CPP_TYPE_LONG)
  3641.       return DoOutput("CARDINAL");
  3642.     if(t->Type == CPP_TYPE_WORD)
  3643.       return DoOutput("WORD");
  3644.     if(t->Type == CPP_TYPE_BYTE)
  3645.       return DoOutput(t->PointerDepth == 1 ? "CHAR" : "BYTE");
  3646.   }
  3647.   else if(t->Type == CPP_TYPE_WORD)
  3648.     return DoOutput("INTEGER");
  3649.   else if(t->Type == CPP_TYPE_BYTE)
  3650.     return DoOutput("SHORTINT");
  3651.   return DoOutput("LONGINT");
  3652. }
  3653.  
  3654. /* ------------------------------------------------------------------ */
  3655.  
  3656. ULONG CallPrag(ULONG tagmode, STRPTR type, FuncType Func)
  3657. {
  3658.   if(type)
  3659.     if((*type && !DoOutput("#if%s\n", type)) ||
  3660.     !(CallFunc(tagmode, tagmode ? 0 : "/%s */\n", Func)) ||
  3661.     (*type && !DoOutput("#endif\n")) || CTRL_C)
  3662.       return 0;
  3663.   return 1;
  3664. }
  3665.  
  3666. ULONG CreatePragmaFile(STRPTR amicall, STRPTR libcall, STRPTR amitags,
  3667. STRPTR libtags, ULONG mode)
  3668. {
  3669.   switch(mode)
  3670.   {
  3671.   case PRAGMODE_PRAGLIB: DoOutput("#ifndef _INCLUDE_PRAGMA_%s_LIB_H\n"
  3672.     "#define _INCLUDE_PRAGMA_%s_LIB_H\n", ShortBaseNameUpper,
  3673.     ShortBaseNameUpper); break;
  3674.   case PRAGMODE_PRAGSLIB: DoOutput("#ifndef PRAGMAS_%s_LIB_H\n#define "
  3675.     "PRAGMAS_%s_LIB_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
  3676.   case PRAGMODE_PRAGSPRAGS: DoOutput("#ifndef PRAGMAS_%s_PRAGMAS_H\n#define "
  3677.     "PRAGMAS_%s_PRAGMAS_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
  3678.   case PRAGMODE_NONE: break;
  3679.   default: return 0;
  3680.   }
  3681.  
  3682.   if(HEADER)
  3683.   {
  3684.     DoOutput("\n");
  3685.     DoOutputDirect(HEADER, headersize);
  3686.   }
  3687.  
  3688.   if(mode != PRAGMODE_NONE && !DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
  3689.   "<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
  3690.     return 0;
  3691.  
  3692.   if((Flags & FLAG_EXTERNC) &&
  3693.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  3694.     return 0;
  3695.  
  3696.   if(Flags & FLAG_GNUPRAG)
  3697.   {
  3698.     DoOutput("#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n#endif\n",
  3699.     ShortBaseName);
  3700.     Flags |= FLAG_DONE;
  3701.   }
  3702.  
  3703.   if(
  3704.   !CallPrag(TAGMODE_NORMAL, amicall, FuncAMICALL) ||
  3705.   !CallPrag(TAGMODE_NORMAL, libcall, FuncLIBCALL))
  3706.     return 0;
  3707.  
  3708.   if(tagfuncs)
  3709.   {
  3710.     if(
  3711.     !CallPrag(TAGMODE_TAGS, amitags, FuncAMICALL) ||
  3712.     !CallPrag(TAGMODE_TAGS, libtags, FuncLIBCALL))
  3713.       return 0;
  3714.   }
  3715.  
  3716.   if((Flags & FLAG_EXTERNC) &&
  3717.   !DoOutput("\n#ifdef __cplusplus\n}\n#endif\n"))
  3718.     return 0;
  3719.  
  3720.   switch(mode)
  3721.   {
  3722.   case PRAGMODE_PRAGLIB: DoOutput("\n#endif\t/*  _INCLUDE_PRAGMA_%s_LIB_H  */\n",
  3723.     ShortBaseNameUpper); break;
  3724.   case PRAGMODE_PRAGSLIB: DoOutput("\n#endif\t/*  PRAGMAS_%s_LIB_H  */\n",
  3725.     ShortBaseNameUpper); break;
  3726.   case PRAGMODE_PRAGSPRAGS: DoOutput("\n#endif\t/*  PRAGMAS_%s_PRAGMA_H  */\n",
  3727.     ShortBaseNameUpper); break;
  3728.   case PRAGMODE_NONE: break;
  3729.   default: return 0;
  3730.   }
  3731.   return Output_Error;
  3732. }
  3733.  
  3734. ULONG CreateCSTUBSFile(void)
  3735. {
  3736.   DoOutput("#ifndef _INCLUDE_%s_CSTUBS_H\n#define _INCLUDE_%s_CSTUBS_H\n",
  3737.     ShortBaseNameUpper, ShortBaseNameUpper);
  3738.  
  3739.   if(!clibdata)
  3740.   {
  3741.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  3742.   }
  3743.  
  3744.   if(HEADER)
  3745.   {
  3746.     DoOutput("\n");
  3747.     DoOutputDirect(HEADER, headersize);
  3748.   }
  3749.  
  3750.   if(!DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
  3751.   "<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
  3752.     return 0;
  3753.  
  3754.   if(!CallFunc(TAGMODE_TAGS, "/%s */\n", FuncCSTUBS))
  3755.     return 0;
  3756.  
  3757.   return DoOutput("#endif\t/*  _INCLUDE_%s_CSTUBS_H  */\n",
  3758.   ShortBaseNameUpper);
  3759. }
  3760.  
  3761. ULONG CreateLVOFile(ULONG mode)
  3762. {
  3763.   STRPTR data = "_LVO_I";
  3764.  
  3765.   if(mode == 2 || mode == 4)
  3766.     data = "_LIB_I";
  3767.  
  3768.   if(!DoOutput("\t\tIFND LIBRARIES_%s%s\nLIBRARIES_%s%s\tSET\t1\n\n",
  3769.   ShortBaseNameUpper, data, ShortBaseNameUpper, data) ||
  3770.   (HEADER && (!DoOutput("\n") || !DoOutputDirect(HEADER, headersize))) ||
  3771.   (mode <= 2 && !CallFunc(TAGMODE_NORMAL, 0, FuncLVOXDEF)) ||
  3772.   !CallFunc(TAGMODE_NORMAL, "\n%s", FuncLVO) ||
  3773.   !DoOutput("\n\n\t\tENDC\n") || CTRL_C)
  3774.     return 0;
  3775.  
  3776.   return 1;
  3777. }
  3778.  
  3779. ULONG CreateAsmStubs(ULONG mode, ULONG callmode)
  3780. {
  3781.   /* 1 = Text, 2 = Code */
  3782.   switch(mode)
  3783.   {
  3784.   case 1:
  3785.     if(HEADER)
  3786.     {
  3787.       DoOutput("\n");
  3788.       DoOutputDirect(HEADER, headersize);
  3789.     }
  3790.     
  3791.     if(!(Flags & FLAG_ASMSECTION))
  3792.       DoOutput("\tSECTION\t\"%s_STUBS\",CODE\n\tXREF\t_%s\n", ShortBaseNameUpper, BaseName);
  3793.     if(!CallFunc(callmode, 0, FuncAsmText))
  3794.       return 0;
  3795.     break;
  3796.   case 2:
  3797.     if(!CallFunc(callmode, 0, FuncAsmCode))
  3798.       return 0;
  3799.     break;
  3800.   }
  3801.  
  3802.   if(CTRL_C)
  3803.     return 0;
  3804.   return 1;
  3805. }
  3806.  
  3807. ULONG CreateProtoFile(ULONG Type)
  3808. {
  3809.   STRPTR str1 = "pragma", str2 = "lib";
  3810.  
  3811.   DoOutput("#ifndef _PROTO_%s_H\n#define _PROTO_%s_H\n", ShortBaseNameUpper,
  3812.   ShortBaseNameUpper);
  3813.  
  3814.   if(HEADER)
  3815.   {
  3816.     DoOutput("\n");
  3817.     DoOutputDirect(HEADER, headersize);
  3818.   }
  3819.  
  3820.   switch(Type)
  3821.   {
  3822.     case 4: str1 = "pragmas"; /* no break; */
  3823.     case 2: str2 = "pragmas"; break;
  3824.     case 3: str1 = "pragmas"; break;
  3825.     case 5: str1 = "local"; str2 = "loc"; break;
  3826.   }
  3827.  
  3828.   DoOutput("\n#ifndef EXEC_TYPES_H\n#include <exec/types.h>\n#endif\n");
  3829.   if(Type != 5)
  3830.     DoOutput("#ifndef CLIB_%s_PROTOS_H\n"
  3831.     "#include <clib/%s_protos.h>\n#endif\n",
  3832.     ShortBaseNameUpper, ShortBaseName);
  3833.   if(Type >= 6)
  3834.   {
  3835.     DoOutput("\n#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n",
  3836.     ShortBaseName);
  3837.     if(Type != 7)
  3838.       DoOutput("#else");
  3839.   }
  3840.   if(Type != 7)
  3841.     DoOutput("\n#include <%s/%s_%s.h>\n", str1, ShortBaseName, str2);
  3842.   if(Type >= 6)
  3843.     DoOutput("#endif\n");
  3844.  
  3845.   if(BaseName)
  3846.   {
  3847.     DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
  3848.     if(Type >= 7)
  3849.       DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
  3850.       "#endif\n");
  3851.     DoOutput("%s;\n#endif\n", BaseName);
  3852.   }
  3853.  
  3854.   Flags |= FLAG_DONE;
  3855.  
  3856.   return DoOutput("\n#endif\t/*  _PROTO_%s_H  */\n", ShortBaseNameUpper);
  3857. }
  3858.  
  3859. ULONG CreateLocalData(STRPTR to, ULONG callmode, STRPTR clibbuf,
  3860. ULONG clibsize)
  3861. {
  3862.   UBYTE a[40];
  3863.  
  3864.   DoOutput("#ifndef _INCLUDE_PROTO_%s_LOC_H\n"
  3865.   "#define _INCLUDE_PROTO_%s_LOC_H\n",
  3866.   ShortBaseNameUpper, ShortBaseNameUpper);
  3867.  
  3868.   if(HEADER)
  3869.   {
  3870.     DoOutput("\n");
  3871.     DoOutputDirect(HEADER, headersize);
  3872.   }
  3873.  
  3874.   DoOutput("\n");
  3875.  
  3876.   { /* copies the include lines */
  3877.     STRPTR str = clibbuf, strend = clibbuf + clibsize;
  3878.     ULONG i = 0;
  3879.  
  3880.     /* works too, when no clibbuf, because then following is everytime false */
  3881.     while(str < strend)
  3882.     {
  3883.       if(!strncmp(str, "#include", 8))
  3884.       {
  3885.     DoOutput("%s\n",str); ++i;
  3886.       }
  3887.       while(*(str++))
  3888.     ;
  3889.     }
  3890.     DoOutput(i ? "\n" : "#include <exec/types.h>\n\n");
  3891.   }
  3892.  
  3893.   if((Flags & FLAG_EXTERNC) &&
  3894.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  3895.     return 0;
  3896.  
  3897.   if(!CallFunc(callmode, 0, FuncLocText))
  3898.     return 0;
  3899.  
  3900.   if((Flags & FLAG_EXTERNC) &&
  3901.   !DoOutput("#ifdef __cplusplus\n}\n#endif\n\n"))
  3902.     return 0;
  3903.  
  3904.   DoOutput("#endif\t/*  _INCLUDE_PROTO_%s_LOC_H  */\n", ShortBaseNameUpper);
  3905.   Out(out.size); /* clears buffer */
  3906.  
  3907.   sprintf(a, "%s_loc.lib", ShortBaseName);
  3908.   if(!CloseDest(to) || !(out.file = Open(a, MODE_NEWFILE)))
  3909.     return 0;
  3910.  
  3911.   CallFunc(callmode, 0, FuncLocCode);
  3912.   
  3913.   return CloseDest(a);
  3914. }
  3915.  
  3916. ULONG CreateInline(ULONG mode)
  3917. {
  3918.   if(!clibdata)
  3919.   {
  3920.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  3921.   }
  3922.  
  3923.   DoOutput("#ifndef _%sINLINE_%s_H\n#define _%sINLINE_%s_H\n",
  3924.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper,
  3925.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
  3926.  
  3927.   if(HEADER)
  3928.   {
  3929.     DoOutput("\n");
  3930.     DoOutputDirect(HEADER, headersize);
  3931.   }
  3932.  
  3933.   DoOutput("\n");
  3934.  
  3935.   if(mode)
  3936.   {
  3937.     if(Flags & FLAG_POWERUP)
  3938.       DoOutput("#ifndef __PPCINLINE_STUB_H\n"
  3939.       "#include <powerup/ppcinline/stubs.h>\n#endif\n\n");
  3940.     else
  3941.       DoOutput("#ifndef __INLINE_STUB_H\n"
  3942.       "#include <inline/stubs.h>\n#endif\n\n");
  3943.     if(mode == 2)
  3944.       Flags |= FLAG_INLINESTUB;
  3945.   }
  3946.   else
  3947.   {
  3948.     if(Flags & FLAG_POWERUP)
  3949.       DoOutput("#ifndef __PPCINLINE_MACROS_H\n"
  3950.       "#include <powerup/ppcinline/macros.h>\n#endif\n\n");
  3951.     else
  3952.       DoOutput("#ifndef __INLINE_MACROS_H\n"
  3953.       "#include <inline/macros.h>\n#endif\n\n");
  3954.     Flags |= FLAG_INLINENEW;
  3955.   }
  3956.  
  3957.   if(BaseName)
  3958.   {
  3959.     if(mode)
  3960.       DoOutput("#ifndef BASE_EXT_DECL\n#define BASE_EXT_DECL\n"
  3961.       "#define BASE_EXT_DECL0 extern struct %s *%s;\n#endif\n"
  3962.       "#ifndef BASE_PAR_DECL\n#define BASE_PAR_DECL\n"
  3963.       "#define BASE_PAR_DECL0 void\n#endif\n"
  3964.       "#ifndef BASE_NAME\n#define BASE_NAME %s\n#endif\n\n"
  3965.       "BASE_EXT_DECL0\n\n", GetBaseType(), BaseName, BaseName);
  3966.     else
  3967.       DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
  3968.       ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
  3969.   }
  3970.  
  3971.   if(!CallFunc(TAGMODE_BOTH, "/%s */\n", FuncInline))
  3972.     return 0;
  3973.  
  3974.   if(mode && BaseName)
  3975.     DoOutput("#undef BASE_EXT_DECL\n#undef BASE_EXT_DECL0\n"
  3976.     "#undef BASE_PAR_DECL\n#undef BASE_PAR_DECL0\n#undef BASE_NAME\n\n");
  3977.  
  3978.   return DoOutput("#endif /*  _%sINLINE_%s_H  */\n",
  3979.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
  3980. }
  3981.  
  3982. ULONG CreateSASPowerUP(void)
  3983. {
  3984.   DoOutput("#ifndef _PPCPRAGMA_%s_H\n#define _PPCPRAGMA_%s_H\n",
  3985.   ShortBaseNameUpper, ShortBaseNameUpper);
  3986.  
  3987.   if(HEADER)
  3988.   {
  3989.     DoOutput("\n");
  3990.     DoOutputDirect(HEADER, headersize);
  3991.   }
  3992.  
  3993.   DoOutput("\n#ifdef __GNUC__\n"
  3994.   "#ifndef _PPCINLINE__%s_H\n"
  3995.   "#include <powerup/ppcinline/%s.h>\n"
  3996.   "#endif\n"
  3997.   "#else\n\n"
  3998.   "#ifndef POWERUP_PPCLIB_INTERFACE_H\n"
  3999.   "#include <powerup/ppclib/interface.h>\n"
  4000.   "#endif\n\n"
  4001.   "#ifndef POWERUP_GCCLIB_PROTOS_H\n"
  4002.   "#include <powerup/gcclib/powerup_protos.h>\n"
  4003.   "#endif\n\n"
  4004.   "#ifndef NO_PPCINLINE_STDARG\n"
  4005.   "#define NO_PPCINLINE_STDARG\n"
  4006.   "#endif /* SAS-C PPC inlines */\n\n",
  4007.   ShortBaseNameUpper, ShortBaseName);
  4008.  
  4009.   if(BaseName)
  4010.   {
  4011.     DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
  4012.     ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
  4013.   }
  4014.  
  4015.   if(!CallFunc(TAGMODE_BOTH, "/%s */\n", FuncPowerUP))
  4016.     return 0;
  4017.  
  4018.   return DoOutput("#endif /* SAS-C PPC pragmas */\n"
  4019.   "#endif /*  _PPCPRAGMA_%s_H  */\n", ShortBaseNameUpper);
  4020. }
  4021.  
  4022. ULONG CreateProtoPowerUP(void)
  4023. {
  4024.   DoOutput("#ifndef PPCPROTO_%s_H\n#define PPCPROTO_%s_H\n",
  4025.   ShortBaseNameUpper, ShortBaseNameUpper);
  4026.  
  4027.   if(HEADER)
  4028.   {
  4029.     DoOutput("\n");
  4030.     DoOutputDirect(HEADER, headersize);
  4031.   }
  4032.  
  4033.   DoOutput("\n#include <clib/%s_protos.h>\n\n#ifdef " TEXT_GNUC "\n"
  4034.   "#include <powerup/ppcinline/%s.h>\n#else /* SAS-C */\n"
  4035.   "#include <powerup/ppcpragmas/%s_pragmas.h>\n#endif\n",
  4036.   ShortBaseName, ShortBaseName, ShortBaseName);
  4037.  
  4038.   if(BaseName)
  4039.   {
  4040.     DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
  4041.     DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
  4042.     "#endif\n%s;\n#endif\n", BaseName);
  4043.   }
  4044.  
  4045.   Flags |= FLAG_DONE;
  4046.  
  4047.   return DoOutput("\n#endif\t/*  PPCPROTO_%s_H  */\n", ShortBaseNameUpper);
  4048. }
  4049.  
  4050. ULONG CreateFPCUnit(void)
  4051. {
  4052.   if(!clibdata)
  4053.   {
  4054.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  4055.   }
  4056.  
  4057.   DoOutput("UNIT %s;\n", ShortBaseNameUpper);
  4058.  
  4059.   if(HEADER)
  4060.   {
  4061.     DoOutput("\n");
  4062.     DoOutputDirect(HEADER, headersize);
  4063.   }
  4064.  
  4065.   DoOutput("\nINTERFACE\nUSES Exec;\n\nVAR %s : p%s;\n\n", BaseName,
  4066.   GetBaseType());
  4067.  
  4068.   if(!CallFunc(TAGMODE_NORMAL, 0, FuncFPCType))
  4069.     return 0;
  4070.  
  4071.   DoOutput("\nIMPLEMENTATION\n\n");
  4072.  
  4073.   if(!CallFunc(TAGMODE_NORMAL, "(%s *)\n", FuncFPCUnit))
  4074.     return 0;
  4075.  
  4076.   return DoOutput("END. (* UNIT %s *)\n", ShortBaseNameUpper);
  4077. }
  4078.  
  4079. ULONG CreateBMAP(void)
  4080. {
  4081.   return CallFunc(TAGMODE_NORMAL, 0, FuncBMAP);
  4082. }
  4083.  
  4084. /* ------------------------------------------------------------------ */
  4085.  
  4086. ULONG GetName(struct NameList *t, struct ShortListRoot *p, ULONG args)
  4087. {
  4088.   struct NameList *p2 = (struct NameList *) p->First;
  4089.   struct AmiPragma ap;
  4090.   ap.FuncName = t->NormName;
  4091.   ap.NumArgs = 1;
  4092.   ap.Args[0].ArgName = (args ? "args" : "tags");
  4093.   if(!MakeTagFunction(&ap))
  4094.     return 0;
  4095.  
  4096.   while(p2 && strcmp(p2->PragName, ap.TagName))
  4097.    p2 = (struct NameList *) p2->List.Next;
  4098.  
  4099.   if(!p2)
  4100.     return 0;
  4101.  
  4102.   t->Type = (args ? NTP_ARGS : NTP_TAGS);
  4103.   t->PragName = ap.TagName;
  4104.   RemoveItem(p, (struct ShortList *) p2);
  4105.  
  4106. #ifdef DEBUG_OLD
  4107.   VPrintf("GetName: name matches - %s _ %s\n", &t->NormName);
  4108. #endif
  4109.  
  4110.   return 1;
  4111. }
  4112.  
  4113. void OptimizeFDData(struct PragData *pd)
  4114. {
  4115. #ifdef DEBUG_OLD
  4116.   PutStr("OptimizeFDData\n");
  4117. #endif
  4118.  
  4119.   while(pd && !CTRL_C)
  4120.   {
  4121.     if(pd->NumNames > 1)
  4122.     {
  4123.       struct ShortListRoot n = {0,0,0}, p = {0,0,0};
  4124.       struct NameList *t;
  4125.       while(pd->Name.First)    /* sorts in AmiCall and TagCall */
  4126.       {
  4127.     t = (struct NameList *) pd->Name.First;
  4128.  
  4129.     RemoveItem(&pd->Name, (struct ShortList *) t);
  4130.     AddItem(t->PragName ? &p : &n, (struct ShortList *) t);
  4131.       }
  4132.  
  4133.       if(p.First)
  4134.       {
  4135.     t = (struct NameList *) n.First;
  4136.     while(p.First && t)
  4137.     {
  4138.       if(!GetName(t, &p, 0))
  4139.       {
  4140.         GetName(t, &p, 1);
  4141.       }
  4142.       if(t->PragName)
  4143.       {
  4144.         struct NameList *t2 = (struct NameList *) t->List.Next;
  4145.         RemoveItem(&n, (struct ShortList *)t);
  4146.         AddItem(&pd->Name, (struct ShortList *) t);
  4147.         t = t2;
  4148.       }
  4149.       else
  4150.         t = (struct NameList *) t->List.Next;
  4151.     }
  4152.     while(p.First)
  4153.     {
  4154.       if(n.First)
  4155.       {
  4156.         t = (struct NameList *) n.First;
  4157.         t->PragName = ((struct NameList *)(p.First))->PragName;
  4158.         RemoveItem(&n, (struct ShortList *) t);
  4159. #ifdef DEBUG_OLD
  4160.   VPrintf("OptimizeFDData: names together - %s _ %s\n", &t->NormName);
  4161. #endif
  4162.         t->Type = NTP_UNKNOWN;
  4163.       }
  4164.       else
  4165.       {
  4166.         ULONG i;
  4167.  
  4168.         t = (struct NameList *) p.First;
  4169.         i = strlen(t->PragName);
  4170.         t->NormName = DupString(t->PragName, i+1);
  4171.         t->NormName[i++] = 'A';
  4172.         t->NormName[i] = 0;
  4173.         t->Type = NTP_TAGS;
  4174. #ifdef DEBUG_OLD
  4175.   VPrintf("OptimizeFDData: NormName created - %s _ %s\n", &t->NormName);
  4176. #endif
  4177.       }
  4178.  
  4179.       AddItem(&pd->Name, (struct ShortList *) t);
  4180.       RemoveItem(&p, p.First);
  4181.     }
  4182.       }
  4183.  
  4184.       AddItem(&pd->Name, n.First); /* add left NormNames */
  4185.     }
  4186.     pd = (struct PragData *) pd->List.Next;
  4187.   }
  4188. }
  4189.  
  4190. ULONG MakeFD(struct PragList *pl)
  4191. {
  4192.   struct PragData *pd = (struct PragData *) pl->Data.First;
  4193.   ULONG bias;
  4194.  
  4195. #ifdef DEBUG_OLD
  4196.   PutStr("MakeFD\n");
  4197. #endif
  4198.   bias = pd->Bias;
  4199.  
  4200.   OptimizeFDData(pd);
  4201. #ifdef DEBUG_OLD
  4202.   PutStr("MakeFD: after Optimizing\n");
  4203. #endif
  4204.   DoOutput("##base _%s\n##bias %ld\n##public\n", pl->Basename, bias);
  4205.  
  4206.   while(pd && !CTRL_C && Output_Error)
  4207.   {
  4208.     struct NameList *n = (struct NameList *) pd->Name.First;
  4209.  
  4210.     if(bias != pd->Bias)
  4211.       DoOutput("##bias %ld\n", (bias = pd->Bias));
  4212.  
  4213.     while(n)
  4214.     {
  4215.       STRPTR lastpar = "last";
  4216.       ULONG i;
  4217.  
  4218.       if(n->Type == NTP_TAGS)
  4219.     lastpar = "tags";
  4220.       else if(n->Type == NTP_ARGS)
  4221.     lastpar = "args";
  4222.  
  4223.       DoOutput("%s("/*)*/,n->NormName);
  4224.       if(!pd->NumArgs)
  4225.     DoOutput(/*(*/")()\n");
  4226.       else
  4227.       {
  4228.     for(i = 0; i < pd->NumArgs-1; ++i)
  4229.       DoOutput("par%ld,",i+1);
  4230.     DoOutput("%s)(", lastpar);
  4231.     for(i = 0; i < pd->NumArgs-1; ++i)
  4232.       DoOutput("%s,", RegNames[pd->ArgReg[i]]);
  4233.     DoOutput("%s)\n", RegNames[pd->ArgReg[i]]);
  4234.  
  4235.     if(n->Type == NTP_UNKNOWN)
  4236.     {
  4237.       ULONG i;
  4238.       for(i = 0; n->NormName[i] == n->PragName[i]; ++i)
  4239.         ;
  4240.       DoOutput("*tagcall");
  4241.       if(n->NormName[i])
  4242.         DoOutput("-%s", n->NormName+i);
  4243.       if(n->PragName[i])
  4244.         DoOutput("+%s", n->PragName+i);
  4245.  
  4246.       DoOutput("\n");
  4247.     }
  4248.       }
  4249.       if((n = (struct NameList *) n->List.Next))
  4250.     DoOutput("##bias %ld\n", pd->Bias);
  4251.       Flags |= FLAG_DONE;
  4252.     }
  4253.  
  4254.     pd = (struct PragData *)pd->List.Next; bias += 6;
  4255.   }
  4256.  
  4257.   if(CTRL_C)
  4258.     return 0;
  4259.  
  4260.   DoOutput("##end\n");
  4261.  
  4262.   return Output_Error;
  4263. }
  4264.  
  4265. ULONG AddFDData(struct ShortListRoot *pls, struct FDData *fd)
  4266. {
  4267.   struct NameList *t;
  4268.   struct PragList *pl = (struct PragList *) pls->First;
  4269.   struct PragData *pd;
  4270.  
  4271.   while(pl && strcmp(pl->Basename, fd->Basename))
  4272.     pl = (struct PragList *) pl->List.Next;
  4273.  
  4274.   if(!pl)
  4275.   {
  4276. #ifdef DEBUG_OLD
  4277.   VPrintf("AddFDData: New PragList - %s\n", &fd->Basename);
  4278. #endif
  4279.     if(!(pl = (struct PragList *) NewItem(pls)))
  4280.       return 100;
  4281.     pl->Basename = fd->Basename;
  4282.     pl->Data.Size = sizeof(struct PragData);
  4283.     AddItem(pls, (struct ShortList *) pl);
  4284.   }
  4285.  
  4286.   if((pd = (struct PragData *) pl->Data.First))
  4287.   {
  4288.     while(pd->List.Next && ((struct PragData *) pd->List.Next)->Bias
  4289.     <= fd->Bias)
  4290.       pd = (struct PragData *) pd->List.Next;
  4291.   }
  4292.  
  4293.   if(!pd || pd->Bias != fd->Bias)
  4294.   {
  4295.     struct PragData *pd2;
  4296. #ifdef DEBUG_OLD
  4297.   {
  4298.     ULONG args[2];
  4299.     args[0] = fd->Bias;
  4300.     args[1] = fd->NumArgs;
  4301.     VPrintf("AddFDData: New PragData - %ld, %ld\n", &args);
  4302.   }
  4303. #endif
  4304.     if(!(pd2 = (struct PragData *) NewItem(&pl->Data)))
  4305.       return 100;
  4306.     pd2->Bias = fd->Bias;
  4307.     CopyMem(fd->ArgReg, pd2->ArgReg, MAXREG);
  4308.     pd2->NumArgs = fd->NumArgs;
  4309.     pd2->Name.Size = sizeof(struct NameList);
  4310.     if(!pd)
  4311.       AddItem(&pl->Data, (struct ShortList *) pd2);
  4312.     else if(pd->Bias > fd->Bias) /* Insert at start */
  4313.     {
  4314.       pd2->List.Next = pl->Data.First;
  4315.       pl->Data.First = (struct ShortList *) pd2;
  4316.     }
  4317.     else /* Insert the entry */
  4318.     {
  4319.       pd2->List.Next = pd->List.Next;
  4320.       pd->List.Next = (struct ShortList *) pd2;
  4321.     }
  4322.     pd = pd2;
  4323.   }
  4324.   else
  4325.   {
  4326.     ULONG i = fd->NumArgs;
  4327.     if(fd->NumArgs != pd->NumArgs)
  4328.     {
  4329. #ifdef DEBUG_OLD
  4330.   Printf("ArgNum %ld != %ld\n", fd->NumArgs, pd->NumArgs);
  4331. #endif
  4332.       return ERR_DIFFERENT_TO_PREVIOUS;
  4333.     }
  4334.  
  4335.     while(i--)
  4336.     {
  4337.       if(fd->ArgReg[i] != pd->ArgReg[i])
  4338.       {
  4339. #ifdef DEBUG_OLD
  4340.   Printf("ArgReg %lx != %lx\n", fd->ArgReg[i], pd->ArgReg[i]);
  4341. #endif
  4342.     return ERR_DIFFERENT_TO_PREVIOUS;
  4343.       }
  4344.     }
  4345.   }
  4346.  
  4347.   t = (struct NameList *) pd->Name.First;    /* skips same names */
  4348.   while(t && strcmp(fd->Name, fd->Mode ? t->PragName : t->NormName))
  4349.     t = (struct NameList *) t->List.Next;
  4350.  
  4351.   if(t)
  4352.     return 0;
  4353.  
  4354.   if(!(t = (struct NameList *) NewItem(&pd->Name)))
  4355.     return 100;
  4356.   if(fd->Mode)
  4357.     t->PragName = fd->Name;
  4358.   else
  4359.     t->NormName = fd->Name;
  4360.   AddItem(&pd->Name, (struct ShortList *) t);
  4361.   ++(pd->NumNames);
  4362. #ifdef DEBUG_OLD
  4363.   VPrintf("AddFDData: New NameList - %s\n", &fd->Name);
  4364. #endif
  4365.   return 0;
  4366. }
  4367.  
  4368. UBYTE GetHexValue(UBYTE data)
  4369. {
  4370.   if(data >= 'a')
  4371.     return (UBYTE) (data - 'a' + 10);
  4372.   else if(data >= 'A')
  4373.     return (UBYTE) (data - 'A' + 10);
  4374.   else
  4375.     return (UBYTE) (data - '0');
  4376. }
  4377.  
  4378. UBYTE GetDoubleHexValue(UBYTE *data)
  4379. {
  4380.   return (UBYTE)((GetHexValue(*data)<<4)+GetHexValue(data[1]));
  4381. }
  4382.  
  4383. ULONG GetLibData(struct FDData *fd)
  4384. {
  4385.   ULONG i;
  4386.   fd->Name = SkipBlanks(in.pos);
  4387.   in.pos = SkipName(fd->Name); *(in.pos++) = 0;
  4388.   in.pos = SkipBlanks(in.pos);
  4389.   fd->Bias = strtoul(in.pos, 0, 16);
  4390.   in.pos = SkipName(SkipBlanks(SkipName(in.pos)));
  4391.   if((fd->NumArgs = GetHexValue(*(--in.pos))) > MAXREGNF - 2)
  4392.     return ERR_TO_MUCH_ARGUMENTS;
  4393.   --in.pos; /* skips return register */
  4394.   for(i = 0; i < fd->NumArgs; ++i)
  4395.   {
  4396.     if((fd->ArgReg[i] = GetHexValue(*(--in.pos))) > REG_A5)
  4397.       return ERR_EXPECTED_REGISTER_NAME;
  4398.   }
  4399.   return 0;
  4400. }
  4401.  
  4402. ULONG GetFlibData(struct FDData *fd)
  4403. {
  4404.   ULONG i;
  4405.   fd->Name = SkipBlanks(in.pos);
  4406.   in.pos = SkipName(fd->Name); *(in.pos++) = 0;
  4407.   in.pos = SkipBlanks(in.pos);
  4408.   fd->Bias = strtoul(in.pos, 0, 16);
  4409.   in.pos = SkipName(SkipBlanks(SkipName(in.pos))) - 2;
  4410.   if((fd->NumArgs = GetDoubleHexValue(in.pos)) > MAXREG-2)
  4411.     return ERR_TO_MUCH_ARGUMENTS;
  4412.   in.pos -= 2; /* skips return register */
  4413.   for(i = 0; i < fd->NumArgs; ++i)
  4414.   {
  4415.     in.pos -= 2;
  4416.     if((fd->ArgReg[i] = GetDoubleHexValue(in.pos)) >= MAXREG)
  4417.       return ERR_EXPECTED_REGISTER_NAME;
  4418.     else if(fd->ArgReg[i] >= REG_FP0 && (Flags & FLAG_NOFPU))
  4419.       return ERR_FLOATARG_NOT_ALLOWED;
  4420.   }
  4421.   return 0;
  4422. }
  4423.  
  4424. ULONG GetAmiData(struct FDData *fd)
  4425. {
  4426.   STRPTR endptr;
  4427.   in.pos = SkipBlanks(in.pos);
  4428.   if(*in.pos != '('/*)*/)
  4429.     return ERR_EXPECTED_OPEN_BRACKET;
  4430.   fd->Basename = ++in.pos;
  4431.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  4432.   if(*in.pos != ',')
  4433.     return ERR_EXPECTED_COMMA;
  4434.   *endptr = 0;
  4435.   in.pos = SkipBlanks(++in.pos);
  4436.   if(!strncmp(in.pos, "0x", 2))
  4437.     fd->Bias = strtoul(in.pos+2, 0, 16);
  4438.   else
  4439.     fd->Bias = strtoul(in.pos, 0, 10);
  4440.  
  4441.   in.pos = SkipBlanks(SkipName(in.pos));
  4442.   if(*in.pos != ',')
  4443.     return ERR_EXPECTED_COMMA;
  4444.   fd->Name = in.pos = SkipBlanks(++in.pos);
  4445.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  4446.   if(*in.pos != '('/*)*/)
  4447.     return ERR_EXPECTED_OPEN_BRACKET;
  4448.   *endptr = 0;
  4449.   in.pos = SkipBlanks(++in.pos);
  4450.   if(*in.pos == /*(*/')')
  4451.     return 0;
  4452.   --in.pos;
  4453.   while(*in.pos != /*(*/')')
  4454.   {
  4455.     ULONG i;
  4456.     in.pos = SkipBlanks(in.pos+1);
  4457.  
  4458.     for(i = 0; i < REG_FP0; i++)
  4459.       if(!strnicmp(RegNames[i], in.pos, 2))
  4460.     break;
  4461.     if(i == REG_FP0)
  4462.     {
  4463.       for(; i < MAXREG; i++)
  4464.         if(!strnicmp(RegNames[i], in.pos, 3))
  4465.       break;
  4466.     }
  4467.  
  4468.     if(i == MAXREG)
  4469.       return ERR_EXPECTED_REGISTER_NAME;
  4470.     else if(i >= REG_FP0 && (Flags & FLAG_NOFPU))
  4471.       return ERR_FLOATARG_NOT_ALLOWED;
  4472.  
  4473.     fd->ArgReg[fd->NumArgs] = i; ++fd->NumArgs;
  4474.  
  4475.     if(fd->NumArgs > MAXREG-2)
  4476.       return ERR_TO_MUCH_ARGUMENTS;
  4477.  
  4478.     in.pos = SkipBlanks(in.pos+(i >= REG_FP0 ? 3 : 2));
  4479.  
  4480.     if(*in.pos != ',' && *in.pos != ')')
  4481.       return ERR_EXPECTED_CLOSE_BRACKET;
  4482.   }
  4483.   in.pos = SkipBlanks(in.pos+1);
  4484.   if(*in.pos != ')')
  4485.     return ERR_EXPECTED_CLOSE_BRACKET;
  4486.   return 0;
  4487. }
  4488.  
  4489. ULONG CreateFDFile(STRPTR to)
  4490. {
  4491.   struct ShortListRoot pl = {0, 0, sizeof(struct PragList)};
  4492.   ULONG linenum, err = 0, skip;
  4493.  
  4494.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  4495.   {
  4496.     in.pos = SkipBlanks(in.pos);
  4497.     if(!strncmp("#pragma", in.pos, 7))
  4498.     {
  4499.       struct FDData fd;
  4500.  
  4501.       skip = 0;
  4502.       memset(&fd, 0, sizeof(struct FDData));
  4503.  
  4504.       in.pos = SkipBlanks(in.pos+7);
  4505.       if(!strncmp("tagcall", in.pos, 7))
  4506.       {
  4507.     fd.Mode = 1;
  4508.     in.pos = SkipBlanks(in.pos+7);
  4509.     if(*in.pos == '(' /*)*/)    /* Storm method */
  4510.       err = GetAmiData(&fd);
  4511.     else                /* SAS method */
  4512.     {
  4513.       fd.Basename = in.pos;
  4514.       in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  4515.       err = GetLibData(&fd);
  4516.     }
  4517.       }
  4518.       else if(!strncmp("amicall", in.pos, 7))    /* Storm method */
  4519.       {
  4520.     in.pos += 7;
  4521.     err = GetAmiData(&fd);
  4522.       }
  4523.       else if(!strncmp("libcall", in.pos, 7))    /* SAS method */
  4524.       {
  4525.     fd.Basename = SkipBlanks(in.pos+7);
  4526.     in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  4527.     err = GetLibData(&fd);
  4528.       }
  4529.       else if(!strncmp("flibcall", in.pos, 8))    /* SAS method */
  4530.       {
  4531.     fd.Basename = SkipBlanks(in.pos+8);
  4532.     in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  4533.     err = GetFlibData(&fd);
  4534.       }
  4535.       else if(!strncmp("syscall", in.pos, 7))    /* SAS method */
  4536.       {
  4537.     fd.Basename = "SysBase";
  4538.     err = GetLibData(&fd);
  4539.       }
  4540.       else
  4541.     skip = 1;
  4542.  
  4543.       if(err)
  4544.     DoError(err, linenum);
  4545.       else if(skip)
  4546.     ;
  4547.       else if((err = AddFDData(&pl, &fd)))
  4548.       {
  4549.     if(err != 100)
  4550.       DoError(err, linenum);
  4551.     return 0;
  4552.       }
  4553.     }
  4554.     while(*(in.pos++))    /* jumps to first char of next line */
  4555.       ;
  4556.   }
  4557.  
  4558.   if(pl.First && !CTRL_C)
  4559.   {
  4560.     struct PragList *p = (struct PragList *) pl.First;
  4561.     if(!p->List.Next)
  4562.     {
  4563.       if(!to)
  4564.       {
  4565.     STRPTR text;
  4566.     ULONG i;
  4567.  
  4568.     if(ShortBaseName)
  4569.     {
  4570.       text = ShortBaseName; i = strlen(text);
  4571.     }
  4572.     else
  4573.     {
  4574.       text = p->Basename; i = strlen(text)-4;
  4575.     }
  4576.  
  4577.     to = DupString(text, i + sizeof(FDFILEEXTENSION) - 1);
  4578.     CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
  4579.       }
  4580.       if(!(out.file = Open(to, MODE_NEWFILE)))
  4581.         return 0;
  4582.       
  4583.       err = MakeFD(p);
  4584.       CloseDest(to);
  4585.       if(!err)
  4586.         return 0;
  4587.     }
  4588.     else
  4589.     {
  4590.       while(p)
  4591.       {
  4592.     ULONG i;
  4593.     i = strlen(p->Basename) - 4;
  4594.     to = DupString(p->Basename, i + sizeof(FDFILEEXTENSION) - 1);
  4595.     CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
  4596.     if(!(out.file = Open(to, MODE_NEWFILE)))
  4597.       return 0;
  4598.     i = MakeFD(p);
  4599.     CloseDest(to);
  4600.         if(!i)
  4601.           return 0;
  4602.     p = (struct PragList *) p->List.Next;
  4603.       }
  4604.     }
  4605.   }
  4606.  
  4607.   if(CTRL_C)
  4608.     DoError(ERR_USER_ABORT, 0);
  4609.  
  4610.   return 1;
  4611. }
  4612.  
  4613. STRPTR helptext =
  4614. "FDFILE:  the FD file which should be used\n"
  4615. "SPECIAL: 1 - Aztec compiler (xxx_lib.h,     MODE 2, AMICALL)\n"
  4616. "\t 2 - DICE compiler  (xxx_pragmas.h, MODE 3, LIBCALL)\n"
  4617. "\t 3 - SAS compiler   (xxx_pragmas.h, MODE 3, LIBCALL,LIBTAGS)\n"
  4618. "\t 4 - MAXON compiler (xxx_lib.h,     MODE 1, AMICALL)\n"
  4619. "\t 5 - STORM compiler (xxx_lib.h,     MODE 1, AMITAGS,AMICALL)\n"
  4620. "\t 6 - all compilers [default]\n"
  4621. "\t 7 - all compilers with pragma to inline redirect for GCC\n"
  4622. "\t 8 - pragma to inline redirect for GCC\n"
  4623. "\t10 - stub-functions for C - C text\n"
  4624. "\t11 - stub-functions for C - assembler text\n"
  4625. "\t12 - stub-functions for C - assembler text (SECTION)\n"
  4626. "\t13 - stub-functions for C - link library\n"
  4627. "\t14 - defines and link library for local library base (register call)\n"
  4628. "\t15 - defines and link library for local library base (stack call)\n"
  4629. "\t16 - stub-functions for Pascal - assembler text\n"
  4630. "\t17 - stub-functions for Pascal - link library\n"
  4631. "\t18 - BMAP file for AmigaBASIC and MaxonBASIC\n"
  4632. "\t20 - assembler lvo _lvo.i file\n"
  4633. "\t21 - assembler lvo _lib.i file\n"
  4634. "\t22 - assembler lvo _lvo.i file no XDEF\n"
  4635. "\t23 - assembler lvo _lib.i file no XDEF\n"
  4636. "\t30 - proto file with pragma/..._lib.h call\n"
  4637. "\t31 - proto file with pragma/..._pragmas.h call\n"
  4638. "\t32 - proto file with pragmas/..._lib.h call\n"
  4639. "\t33 - proto file with pragmas/..._pragmas.h call\n"
  4640. "\t34 - proto file with local/..._loc.h call\n"
  4641. "\t35 - proto file for all compilers\n"
  4642. "\t36 - proto file for GNU-C compiler only\n"
  4643. "\t40 - GCC inline file (preprocessor based)\n"
  4644. "\t41 - GCC inline file (old type - inline based)\n"
  4645. "\t42 - GCC inline file (library stubs)\n"
  4646. "\t50 - GCC inline files for PowerUP (preprocessor based)\n"
  4647. "\t51 - GCC inline files for PowerUP (old type - inline based)\n"
  4648. "\t52 - GCC inline files for PowerUP (library stubs)\n"
  4649. "\t53 - SAS-C include file for PowerUP\n"
  4650. "\t54 - Proto file for PowerUP\n"
  4651. "\t60 - FPC pascal unit text\n"
  4652. "\t80 - FD file (source is a pragma file!)\n"
  4653. "MODE:\t SPECIAL 1-8,AMICALL,LIBCALL,AMITAGS,LIBTAGS:\n"
  4654. "\t 1 - _INCLUDE_PRAGMA_..._LIB_H definition method [default]\n"
  4655. "\t 2 - _PRAGMAS_..._LIB_H definition method\n"
  4656. "\t 3 - _PRAGMAS_..._PRAGMAS_H definition method\n"
  4657. "\t 4 - no definition\n"
  4658. "\t SPECIAL 11-15:\n"
  4659. "\t 1 - all functions, normal interface\n"
  4660. "\t 2 - only tag-functions, tagcall interface [default]\n"
  4661. "\t 3 - all functions, normal and tagcall interface\n"
  4662. "TO:\t the destination directory (self creation of filename) or\n"
  4663. "\t the destination file\n"
  4664. "CLIB:    name of the prototypes file in clib directory\n"
  4665. "HEADER:  inserts given file into header of created file (\"\" is scan)\n"
  4666. "The following four need a string as argument. This string is used to set\n"
  4667. "a #if<given string> before the set method.\n"
  4668. "AMICALL: creates amicall pragmas\n"
  4669. "LIBCALL: creates libcall pragmas\n"
  4670. "AMITAGS: creates tagcall pragmas (amicall like method (StormC++))\n"
  4671. "LIBTAGS: creates tagcall pragmas (libcall like method (SAS C))\n"
  4672. "Switches:\n"
  4673. "COMMENT:    copy comments found in FD file\n"
  4674. "EXTERNC:    add a #ifdef __cplusplus ... statement to pragma file\n"
  4675. "FPUONLY:    work only with functions using FPU register arguments\n"
  4676. "NOFPU:      disable usage of FPU register arguments\n"
  4677. "PRIVATE:    includes private declared functions\n"
  4678. "SMALLDATA:  generate small data link libraries or assembler text\n"
  4679. "SORTED:     sort generated files by name and not by bias value\n"
  4680. "STORMFD:    converts FD files of strange StormC++ format\n"
  4681. "USESYSCALL: uses syscall pragma instead of libcall SysBase\n";
  4682.  
  4683. void main(void)
  4684. {
  4685.   ULONG mode = 0, pragmode = PRAGMODE_PRAGLIB, callmode = TAGMODE_TAGS;
  4686.   ULONG spec = 0; /* for default setting I need a ULONG var to get a pointer */
  4687.   UBYTE filename[255];    /* needed for filename */
  4688.   struct Args args;
  4689.   STRPTR clibbuf = 0;
  4690.   ULONG clibsize = 0;
  4691.  
  4692. #ifdef __SASC    /* with __MAXON__ this is done automatic by my StartUp */
  4693.   TestOS;
  4694. #endif
  4695.  
  4696.   memset(&args, 0, sizeof(struct Args)); /* initialize */
  4697.   args.SPECIAL = &spec;
  4698.  
  4699.   if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  4700.     End(RETURN_FAIL);
  4701.   rda->RDA_ExtHelp = helptext;
  4702.   if(!ReadArgs(PARAM, (LONG *) &args, rda))
  4703.     End(RETURN_FAIL);
  4704.  
  4705.   if(!(in.file = Open(args.FDFILE, MODE_OLDFILE)))
  4706.   {
  4707.     DoError(ERR_OPEN_FILE, 0, args.FDFILE);
  4708.     End(RETURN_FAIL);
  4709.   }
  4710.  
  4711.   VPrintf("SourceFile: %s\n", &args.FDFILE);
  4712.  
  4713.   if(!(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)) ||
  4714.   !ExamineFH(in.file, fib) ||
  4715.   !(in.buf = in.pos = AllocListMem((in.size = fib->fib_Size)+1)) ||
  4716.   Read(in.file, in.buf, in.size) != in.size ||
  4717.   !(out.buf = out.pos = AllocListMem(out.size)))
  4718.     End(RETURN_FAIL);
  4719.   else
  4720.   {
  4721.     STRPTR ptr = FilePart(args.FDFILE);
  4722.     LONG len = strlen(ptr) - sizeof(FDFILEEXTENSION) + 1;
  4723.     if(len >= 0 && !stricmp(ptr+len, FDFILEEXTENSION))
  4724.     {
  4725.       ShortBaseName = ptr;
  4726.       ptr[len] = '\0';
  4727.     }
  4728.   }
  4729.  
  4730.   MakeLines(in.pos, in.size);
  4731.  
  4732.   if(args.EXTERNC)    Flags ^= FLAG_EXTERNC;
  4733.   if(args.STORMFD)    Flags ^= FLAG_STORMFD;
  4734.   if(args.PRIVATE)    Flags ^= FLAG_PRIVATE;
  4735.   if(args.SMALLDATA)    Flags ^= FLAG_SMALLDATA;
  4736.   if(args.USESYSCALL)     Flags ^= FLAG_SYSCALL;
  4737.   if(args.NOFPU)    Flags ^= FLAG_NOFPU;
  4738.   if(args.FPUONLY)    Flags ^= FLAG_FPUONLY;
  4739.   if(args.COMMENT && !args.SORTED)
  4740.     Flags ^= FLAG_DOCOMMENT;
  4741.  
  4742.   if(args.TO)
  4743.   {
  4744.     if((lock = Lock(args.TO, SHARED_LOCK)) && Examine(lock, fib) &&
  4745.     fib->fib_DirEntryType > 0)
  4746.       args.TO = 0;
  4747.     else if(lock)
  4748.     {
  4749.       UnLock(lock);
  4750.       lock = 0;
  4751.     }
  4752.   }
  4753.  
  4754.   if(*args.SPECIAL == 80)
  4755.   {
  4756.     STRPTR ptr = FilePart(args.FDFILE), ptr2;
  4757.  
  4758.     for(ptr2 = ptr; *ptr2 && *ptr2 != '_' && *ptr2 != '.'; ++ptr2)
  4759.       ;
  4760.     if(ptr2 != ptr)
  4761.     {
  4762.       ShortBaseName = ptr;
  4763.       *ptr2 = '\0';
  4764.     }
  4765.     if(lock)
  4766.       oldfh = CurrentDir(lock);
  4767.     if(!CreateFDFile(args.TO))
  4768.       End(RETURN_FAIL);
  4769.     End(RETURN_OK);
  4770.   }
  4771.  
  4772.   Close(in.file);
  4773.   if((in.file = Open(EXTTYPESFILE, MODE_OLDFILE)) ||
  4774.   (in.file = Open(EXTTYPESFILE2, MODE_OLDFILE)))
  4775.   {
  4776.     STRPTR ptr;
  4777.  
  4778.     if(ExamineFH(in.file, fib) && (ptr = AllocListMem(fib->fib_Size)) &&
  4779.     Read(in.file, ptr, fib->fib_Size) == fib->fib_Size)
  4780.     {
  4781.       ULONG i;
  4782.       if((i = ScanTypes(ptr, fib->fib_Size)) > 0)
  4783.         DoError(ERR_WRONG_TYPES_LINE, i);
  4784.       if(i)
  4785.         End(RETURN_FAIL);
  4786.     }
  4787.     else
  4788.       End(RETURN_FAIL);
  4789.  
  4790.     Close(in.file); in.file = 0;
  4791.   }
  4792.  
  4793.   if(args.CLIB)
  4794.   {
  4795.     if(!(in.file = Open(args.CLIB, MODE_OLDFILE)))
  4796.     {
  4797.       DoError(ERR_OPEN_FILE, 0, args.CLIB);
  4798.       End(RETURN_FAIL);
  4799.     }
  4800.     if(!ExamineFH(in.file, fib) ||
  4801.     !(clibbuf = AllocListMem((clibsize = fib->fib_Size + 1))) ||
  4802.     Read(in.file, clibbuf, fib->fib_Size) != fib->fib_Size)
  4803.       End(RETURN_FAIL);
  4804.     ScanClibFile(clibbuf, clibbuf+fib->fib_Size);
  4805.     Close(in.file); in.file = 0;
  4806.   }
  4807.  
  4808.   if(lock)
  4809.     oldfh = CurrentDir(lock);
  4810.  
  4811.   if(!ScanFDFile())
  4812.     End(RETURN_FAIL);
  4813.  
  4814.   if(args.SORTED)
  4815.     SortFDList();
  4816.  
  4817.   if(!ShortBaseName)
  4818.   {
  4819.     DoError(ERR_MISSING_SHORTBASENAME, 0); End(RETURN_FAIL);
  4820.   }
  4821.   else if((ShortBaseNameUpper = DupString(ShortBaseName,
  4822.   strlen(ShortBaseName))))
  4823.   {
  4824.     STRPTR a = ShortBaseNameUpper;
  4825.     while((*a = toupper(*a)))    /* Convert to uppercase */
  4826.       a++;
  4827.   }
  4828.   else
  4829.     End(RETURN_FAIL);
  4830.  
  4831.   if(*args.SPECIAL < 10) /* the pragma area is up to 9 */
  4832.   {
  4833.     STRPTR amicall = 0, libcall = 0, amitags = 0, libtags = 0;
  4834.  
  4835.     mode = MODUS_PRAGMA;
  4836.     sprintf(filename, "%s_lib.h", ShortBaseName);
  4837.  
  4838.     if(!args.LIBTAGS && !args.AMITAGS && !args.LIBCALL && !args.AMICALL &&
  4839.     !*args.SPECIAL)
  4840.       *args.SPECIAL = 6; /* default mode */
  4841.  
  4842.     switch(*args.SPECIAL)
  4843.     {
  4844.       case 0: break;
  4845.       case 1: pragmode = PRAGMODE_PRAGSLIB; amicall = ""; break;
  4846.       case 2: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  4847.           pragmode = PRAGMODE_PRAGSPRAGS; libcall = ""; break;
  4848.       case 3: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  4849.           pragmode = PRAGMODE_PRAGSPRAGS; libcall = "";
  4850.           libtags = "def " TEXT_SAS_60; break;
  4851.       case 4: amicall = ""; break;
  4852.       case 5: amicall = amitags = ""; break;
  4853.       case 7: Flags |= FLAG_GNUPRAG; /* no break ! */
  4854.       case 6: amicall = " defined(" TEXT_AZTEC ") || defined("
  4855.     TEXT_MAXON ") || defined(" TEXT_STORM ")";
  4856.     libcall = " defined(" TEXT_DICE ") || defined(" TEXT_SAS ")";
  4857.     libtags = "def " TEXT_SAS_60; amitags ="def " TEXT_STORM; break;
  4858.       case 8: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  4859.               Flags |= FLAG_GNUPRAG; pragmode = PRAGMODE_PRAGSPRAGS; break;
  4860.       default: mode = MODUS_ERROR; break;
  4861.     }
  4862.  
  4863.     if(!args.AMICALL)    args.AMICALL = amicall;
  4864.     if(!args.LIBCALL)    args.LIBCALL = libcall;
  4865.     if(!args.AMITAGS)    args.AMITAGS = amitags;
  4866.     if(!args.LIBTAGS)    args.LIBTAGS = libtags;
  4867.  
  4868.     if(args.MODE && *args.MODE > 0 && *args.MODE < 5)
  4869.       pragmode = *args.MODE;
  4870.   }
  4871.   else if(*args.SPECIAL < 20) /* the misc area is up to 19 */
  4872.   {
  4873.     if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
  4874.       callmode = *args.MODE - 1;
  4875.     switch(*args.SPECIAL)
  4876.     {
  4877.     case 10: mode = MODUS_CSTUB;
  4878.       sprintf(filename, "%s_cstub.h", ShortBaseName); break;
  4879.     case 12: Flags |= FLAG_ASMSECTION; /* no break! */
  4880.     case 11: mode = MODUS_STUBTEXT;
  4881.       sprintf(filename, "%s_stub.a", ShortBaseName); break;
  4882.     case 13: mode = MODUS_STUBCODE;
  4883.       sprintf(filename, "%s.lib", ShortBaseName); break;
  4884.     case 14: Flags |= FLAG_LOCALREG; /* no break ! */
  4885.     case 15: mode = MODUS_LOCALDATA;
  4886.       sprintf(filename, "%s_loc.h", ShortBaseName); args.TO = 0; break;
  4887.     case 16: mode = MODUS_STUBTEXT; callmode = TAGMODE_NORMAL;
  4888.       Flags ^= FLAG_PASCAL;
  4889.       sprintf(filename, "%s_stub.a", ShortBaseName); break;
  4890.     case 17: mode = MODUS_STUBCODE; callmode = TAGMODE_NORMAL;
  4891.       Flags ^= FLAG_PASCAL;
  4892.       sprintf(filename, "%s.lib", ShortBaseName); break;
  4893.     case 18: mode = MODUS_BMAP; callmode = TAGMODE_NORMAL;
  4894.       sprintf(filename, "%s.bmap", ShortBaseName); break;
  4895.     default: mode = MODUS_ERROR; break;
  4896.     }
  4897.   }
  4898.   else if(*args.SPECIAL < 30) /* the lvo area is up to 29 */
  4899.   {
  4900.     switch(*args.SPECIAL)
  4901.     {
  4902.     case 20: case 22: mode = MODUS_LVO+*args.SPECIAL-20;
  4903.       sprintf(filename, "%s_lvo.i", ShortBaseName); break;
  4904.     case 21: case 23: mode = MODUS_LVO+*args.SPECIAL-20;
  4905.       sprintf(filename, "%s_lib.i", ShortBaseName); break;
  4906.     default: mode = MODUS_ERROR; break;
  4907.     }
  4908.   }
  4909.   else if(*args.SPECIAL < 40) /* the proto area is up to 39 */
  4910.   {
  4911.     if(*args.SPECIAL < 37)
  4912.     {
  4913.       mode = MODUS_PROTO+*args.SPECIAL-30;
  4914.       sprintf(filename, "%s.h", ShortBaseName);
  4915.     }
  4916.     else
  4917.       mode = MODUS_ERROR;
  4918.   }
  4919.   else if(*args.SPECIAL < 50) /* the inline area is up to 49 */
  4920.   {
  4921.     switch(*args.SPECIAL)
  4922.     {
  4923.     case 40: case 41: case 42: mode = MODUS_INLINE+*args.SPECIAL-40;
  4924.       sprintf(filename, "%s.h", ShortBaseName); break;
  4925.     default: mode = MODUS_ERROR; break;
  4926.     }
  4927.   }
  4928.   else if(*args.SPECIAL < 60) /* the PowerUP area is up to 59 */
  4929.   {
  4930.     switch(*args.SPECIAL)
  4931.     {
  4932.     case 50: case 51: case 52: mode = MODUS_INLINE+*args.SPECIAL-50;
  4933.       sprintf(filename, "%s.h", ShortBaseName); Flags |= FLAG_POWERUP;
  4934.       break;
  4935.     case 53:
  4936.       sprintf(filename, "%s_pragmas.h", ShortBaseName);
  4937.       mode = MODUS_SASPOWER; break;
  4938.     case 54:
  4939.       sprintf(filename, "%s.h", ShortBaseName);
  4940.       mode = MODUS_PROTOPOWER; break;
  4941.     default: mode = MODUS_ERROR; break;
  4942.     }
  4943.   }
  4944.   else if(*args.SPECIAL < 70) /* the PASCAL stuff */
  4945.   {
  4946.     if(*args.SPECIAL == 60)
  4947.     {
  4948.       mode = MODUS_PASCAL;
  4949.       sprintf(filename, "%s.pas", ShortBaseName);
  4950.     }
  4951.     else
  4952.       mode = MODUS_ERROR;
  4953.   }
  4954.  
  4955.   if(!mode)
  4956.   {
  4957.     SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  4958.     End(RETURN_FAIL);
  4959.   }
  4960.   else if(mode == MODUS_ERROR)
  4961.   {
  4962.     SetIoErr(ERROR_TOO_MANY_ARGS);
  4963.     End(RETURN_FAIL);
  4964.   }
  4965.  
  4966.   /* These modes need BaseName always. */
  4967.   if(!BaseName && (mode == MODUS_PRAGMA || mode == MODUS_STUBTEXT ||
  4968.   mode == MODUS_STUBCODE))
  4969.   {
  4970.     DoError(ERR_MISSING_BASENAME, 0); End(RETURN_FAIL);
  4971.   }
  4972.  
  4973.   if(!args.TO)
  4974.     args.TO = filename;
  4975.  
  4976.   if(args.HEADER)
  4977.   {
  4978.     if(!*args.HEADER)
  4979.       args.HEADER = args.TO;
  4980.     if(!(in.file = Open(args.HEADER, MODE_OLDFILE)) ||
  4981.     !ExamineFH(in.file, fib) ||
  4982.     !(HEADER = AllocListMem((headersize = fib->fib_Size)+1)) ||
  4983.     Read(in.file, HEADER, headersize) != headersize)
  4984.       End(RETURN_FAIL);
  4985.     if(args.HEADER == args.TO)
  4986.       FindHeader();
  4987.     Close(in.file);
  4988.     in.file = 0;
  4989.   }
  4990.  
  4991.   if(!(out.file = Open(args.TO, MODE_NEWFILE)))
  4992.     End(RETURN_FAIL);
  4993.  
  4994.   SetIoErr(0);
  4995.  
  4996.   /* from here mode is used as return result */
  4997.   if(mode == MODUS_PRAGMA)
  4998.     mode = CreatePragmaFile(args.AMICALL, args.LIBCALL, args.AMITAGS,
  4999.     args.LIBTAGS, pragmode);
  5000.   else if(mode == MODUS_CSTUB)
  5001.     mode = CreateCSTUBSFile();
  5002.   else if(mode == MODUS_LOCALDATA)
  5003.     mode = CreateLocalData(args.TO, callmode, clibbuf, clibsize);
  5004.   else if(mode == MODUS_SASPOWER)
  5005.     mode = CreateSASPowerUP();
  5006.   else if(mode == MODUS_PROTOPOWER)
  5007.     mode = CreateProtoPowerUP();
  5008.   else if(mode == MODUS_PASCAL)
  5009.     mode = CreateFPCUnit();
  5010.   else if(mode == MODUS_BMAP)
  5011.     mode = CreateBMAP();
  5012.   else if(mode >= MODUS_INLINE)
  5013.     mode = CreateInline(mode-MODUS_INLINE);
  5014.   else if(mode >= MODUS_PROTO)
  5015.     mode = CreateProtoFile(mode-MODUS_PROTO+1);
  5016.   else if(mode >= MODUS_LVO)
  5017.     mode = CreateLVOFile(mode-MODUS_LVO+1);
  5018.   else if(mode)             /* MODUS_STUBTEXT starts with 1 */
  5019.     mode = CreateAsmStubs(mode, callmode);
  5020.  
  5021.   CloseDest(args.TO);
  5022.  
  5023.   if(CTRL_C)
  5024.     DoError(ERR_USER_ABORT, 0);
  5025.   else if(!mode)
  5026.   {
  5027.     DoError(Output_Error ? ERR_UNKNOWN_ERROR : ERR_WRITING_FILE, 0);
  5028.     End(RETURN_FAIL);
  5029.   }
  5030.  
  5031.   End(RETURN_OK);
  5032. }
  5033.  
  5034. void End(ULONG err)
  5035. {
  5036.   if(err && !(Flags & FLAG_DIDERROR))
  5037.     PrintFault(IoErr(), 0);
  5038.  
  5039.   if(fib)        FreeDosObject(DOS_FIB, fib);
  5040.   if(in.file)        Close(in.file);
  5041.   if(lock)
  5042.   {
  5043.     CurrentDir(oldfh);
  5044.     UnLock(lock);
  5045.   }
  5046.   if(remember)        FreeListMem();
  5047.   if(rda)
  5048.   {
  5049.     FreeArgs(rda);
  5050.     FreeDosObject(DOS_RDARGS, rda);
  5051.   }
  5052.   exit(err);
  5053. }
  5054.